Vue pass parameter using handlebars - node.js

Hello i use nodejs with express and handlebars and vue 2.6
I want pass {{audioannotationid}} to my vue component but i can't,
what are i'm doing wrong?
sorry for my english
This my edit.hbs
<div> Editar audio annnotations</div>
<div id="EditAudioannotations" idParametro="beowulfdgo" >
</div>
{{audioannotationid}}
This my component
<template>
<div id="EditAudioannotations" >Hola {{who}}
{{valor}}
</div>
</template>
<script>
export default {
name: 'EditAudioannotations',
props:{idParametro:{
type: String,
default: '0',
},},
data() {
return {
who:"world",
json: {},
valor:"otro valor"
};
},
methods: {
},
beforeMount() {
},
};
</script>
<style></style>
This my index.js
if(window.location.pathname.match(/\/audioannotations\/edit\//)){
// window.Vue = Vue
Vue.use(VueAxios, axios);
Vue.component("EditAudioannotations", EditAudioannotations);
window.vm = new Vue({
el: '#EditAudioannotations',
render: h => h(EditAudioannotations)
})
}
This muy result

I resolved obtain id from url becase i don't use routex, in vue add this method
created() {
var currentUrl = window.location.pathname;
this.ruta=currentUrl
//console.log(currentUrl);
var ultimoSlash = this.ruta.lastIndexOf("/");
this.ruta=this.ruta.substring(ultimoSlash+1)
},

Related

How to emit data in Vue after api call is finished

I have a windows.addEventListener that triggers an API call. I need to pass a name from the api call to the parent component to display it as a title on a dashboard. How can I emit the data to my parent component
child:
<sankey-input-details v-if="!tableLoading" :cardListData="dataFromApi"/>
async apiData() {
const nodeData = this.dateRange
? await get('nodeData', {
dateStart: this.dateRange[0],
dateEnd: this.dateRange[1],
nodeName: this.nodeName
}) : await get('nodeData', {
nodeName: this.nodeName
});
nodeData[0].name <-------- data to be emitted.
this.tableLoading = false;
parent:
props: {
title: String,
cardListData: Array
},
Here you go, You can emit the event to parent from child by using $emit function.
Vue.component('child', {
props: ['childmsg'],
template: '<p>{{ childmsg }}</p>',
mounted() {
// Just for the demo I am emiting the value directly but you can replace that with your API call code.
const nodeData = [{
name: 'Parent Header'
}];
this.$emit('headername', nodeData[0].name);
}
});
var app = new Vue({
el: '#app',
data: {
headerText: null
},
methods: {
showName(e) {
this.headerText = e;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h1>{{ headerText }}</h1>
<child childmsg="This is a child component" #headername="showName"></child>
</div>
https://vuejs.org/guide/components/events.html#emitting-and-listening-to-events
The $emit() method is also available on the component instance as this.$emit():
so in your method:
this.$emit('emitName', nodeData[0].name)

How to paginate a list of posts belonging to a specific category in GatsbyJS

I have developed a blog with Gatsby JS and I managed to add categories to each markdown file so that I can create pages by querying a specific category and list all the posts related to that category.
Now, I'm trying to add pagination to avoid an infinite list of posts inside each category page.
I have been following the official guide here: https://www.gatsbyjs.org/docs/adding-pagination/
And this is the code I came up with:
gatsby-node.js
const path = require('path')
const _ = require("lodash")
const { createFilePath } = require("gatsby-source-filesystem")
exports.createPages = ({actions, graphql}) => {
const {createPage} = actions
const articleTemplate = path.resolve(`src/templates/article.js`)
const categoryTemplate = path.resolve("src/templates/category.js")
return new Promise((resolve, reject) => {
resolve(
graphql(
`
{
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] }
limit: 2000
) {
edges {
node {
html
id
frontmatter {
path
title
categories
}
}
}
}
}
`).then(result => {
if (result.errors) {
reject(result.errors)
}
const articles = result.data.allMarkdownRemark.edges
const articlesPerPage = 6
const numPages = Math.ceil(articles.length / articlesPerPage)
//Creating a page for each article
articles.forEach(({ node }) => {
createPage({
path: node.frontmatter.path,
component: articleTemplate,
//context: {}, // additional data can be passed via context
})
})
// Categories pages:
let categories = []
// Iterate through each article, putting all found categories into `categories`
_.each(articles, edge => {
if (_.get(edge, "node.frontmatter.categories")) {
categories = categories.concat(edge.node.frontmatter.categories)
}
})
Array.from({ length: numPages }).forEach((category, _, i) => {
createPage({
path: i === 0 ? `/${_.kebabCase(category)}/` : `/${_.kebabCase(category)}/${i + 1}`,
component: categoryTemplate,
context: {
limit: articlesPerPage,
skip: i * articlesPerPage,
category,
},
})
})
})
)
})
/templates/categories.js
import React from "react"
import PropTypes from "prop-types"
import Layout from '../layouts/layout'
import ArticleCard from '../components/articles/articlecard'
// Components
import { Link, graphql } from "gatsby"
const _ = require("lodash")
const Categories = ({ pageContext, data }) => {
const { category } = pageContext
const { edges } = data.allMarkdownRemark
return (
<Layout>
<section class="hero is-info is-medium has-text-centered">
<div class="hero-body">
<div class="container">
<h1 class="title is-top">
{category}
</h1>
</div>
</div>
</section>
<div class="section">
<div class="container">
<div class="columns is-multiline">
{edges.map(({ node }) => {
const { path, title, date } = node.frontmatter
return (
<div class="column is-half">
<div class="card">
<div class="card-header">
<p class="card-header-content">{date}</p>
</div>
<div class="card-content">
<Link to={_.kebabCase(category)}><span class="tag is-success has-padding">{category}</span></Link>
<Link to={path}>
<h2 class="title is-4">{title}</h2>
</Link>
</div>
<div class="card-footer">
<div class="card-footer-item"><Link to={path}><div class="button is-success is-inverted is-fullwidth">Read</div></Link></div>
<div class="card-footer-item"><Link to={path}><div class="button is-info is-inverted is-fullwidth">Share on Linkedin</div></Link></div>
</div>
</div>
</div>
)
})}
</div>
</div>
</div>
</Layout>
)
}
Categories.propTypes = {
pageContext: PropTypes.shape({
category: PropTypes.string.isRequired,
}),
data: PropTypes.shape({
allMarkdownRemark: PropTypes.shape({
totalCount: PropTypes.number.isRequired,
edges: PropTypes.arrayOf(
PropTypes.shape({
node: PropTypes.shape({
frontmatter: PropTypes.shape({
path: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
}),
}),
}).isRequired
),
}),
}),
}
export default Categories
export const pageQuery = graphql`
query($skip: Int!, $limit: Int!, $category: String) {
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
filter: { frontmatter: { categories: { in: [$category] } } }
limit: $limit
skip: $skip
) {
totalCount
edges {
node {
frontmatter {
title
path
date(formatString: "MMMM DD, YYYY")
}
}
}
}
}
`
This does not work and it is now throwing the error: error gatsby-node.js returned an error, TypeError: _.kebabCase is not a function
However kebabCase was used smoothly before modifying the query to add pagination, so I don't think the problem is actually there.
Does anyone have any clue?
Thank you!
You are declaring the variable "underscore" twice:
1- from the lodash library
2- from the forEach function:
Array.from({ length: numPages }).forEach((category, _, i)
just change the the second variable to another arbitrary name like this:
Array.from({ length: numPages }).forEach((category, otherName, i)

How to add img src attribute with VueJs

In my NodeJs route, I have the following:
router.get('/list/:id', function(req, res, next) {
request("http://localhost:3000/api/journal/" + req.params.id, function(error, response, body) {
var json = JSON.parse(body);
res.render('listdetail', { title: 'Journal', data: json });
});
});
The data is a json object containing all my screen fields. One of the fields is a base64 presentation of an image.
Then, in my List Detail html I have the following:
<div id="app">
<img class="materialboxed" src="{{data.base64Image}}" width="200">
</div>
This is surely not working... How can I add to the src attribute the base64 information that was sent by NodeJS?
I tried also the following:
<img class="materialboxed" :src=imagebase64Source width="200">
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
imagebase64Source: {{data.base64Image}}
}
})
</script>
But it obviously does not work
Thanks
EDIT:
Strange, it's working now!
Here's what I've done:
<img class="materialboxed" src="{{ data.base64Image }}" width="200">
The only difference I can see is the spacing between the mustache.
Thanks to all who helped.
You can do it simply like this:
<template>
<div>
<img :src="image"/>
</div>
</template>
<script>
module.exports = {
data: function() {
return {
image: //your b64 string there
};
}
};
</script>
Pay attention by the way, depending on what you have on your string, you may have to add a header to the raw string.
<template>
<div>
<img :src="imgWithHeader"/>
</div>
</template>
<script>
module.exports = {
data: function() {
return {
image: //your b64 string there
};
},
computed: {
imgWithHeader() {
return 'data:' + MIMETypeOfTheImage + ';base64,' + this.image;
}
}
};
</script>
Of course you should figure out what is the type of the image, in this case.
I think the method you tried should work if the syntax is corrected
So this:
<img class="materialboxed" :src=imagebase64Source width="200">
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
imagebase64Source: {{data.base64Image}}
}
})
</script>
should be changed to this:
<img class="materialboxed" :src="imagebase64Source" width="200">
<script type="text/javascript">
var app = new Vue({
el: '#app',
data () {
return {
imagebase64Source: data.base64Image,
}
}
})
</script>

Semantic UI with React & ES6 imports

I am trying to include Semantic UI with ES6 imports inside my React component.
I am using Grunt with Babel + Browserify.
I have already installed Semantic UI via NPM.
Here is Gruntfile browserify config:
grunt.initConfig({
browserify: {
dist: {
options: {
transform: [
['babelify', {
presets: ['es2015', 'react']
}]
],
watch: true
},
files: {
'./dist/app.js': ['./src/js/app.js']
}
}
},
I have created component like this:
import React from 'react'
import $ from 'jquery'
import dropdown from 'semantic-ui'
class Container extends React.Component {
constructor() {
super()
this.state = {
value: null
}
}
componentDidMount() {
$('.ui.selection.dropdown').dropdown({
dataType: 'jsonp',
apiSettings : {
onResponse: function(githubResponse) {
var
response = {
results : []
}
;
// translate github api response to work with dropdown
$.each(githubResponse.items, function(index, item) {
response.results.push({
name: item.name,
value: item.id
});
});
return response;
},
url: '//api.github.com/search/repositories?q={query}'
},
onChange: (value) => {
this.setState({
value
});
}
});
}
componentDidUpdate() {
$('.ui.dropdown').dropdown('refresh');
}
render() {
return (
<div>
<div>
<h2>Dropdown</h2>
<div className="ui fluid multiple search selection dropdown">
<input type="hidden" name="repo-ids" />
<div className="default text">Select Repos</div>
<i className="dropdown icon"></i>
<div className="menu">
</div>
</div>
</div>
<div>
<div className="ui divider"></div>
<b>Selected value</b> {this.state.value}
</div>
</div>
);
}
};
export default Container
However, when I try to compile this code, I get:
Error: Cannot find module 'semantic-ui'
Any help ? Do I need to setup browserify somehow, to compile Semantic UI ?
Actually, there is a separate library of Semantic-UI for Reactjs. You need to install that and use it in your Reactjs application. To install just do npm install semantic-ui-react --save and you can find everything. Here is a link to its official site: semantic-ui-react

React and Socket.io

I'm trying to create a simple app using ReactJS and Socket.io
In my component I want to be able to communicate with the server, but the problem is that I don't know how to do io.connect()
1.Do I need to explicitly specify the IP address like io.connect("http://myHost:7000") or is it enough to say : io.connect() ? As we can see in this piece of code :
https://github.com/DanialK/ReactJS-Realtime-Chat/blob/master/client/app.jsx
2.I do more or less the same as this code , but I receive error when I do npm start as io is undefined. I think , io is provided globally by including the socket.io script. How can I solve this problem ?
'use strict';
var React = require('react');
var socket = io.connect();
var chatWindow = React.createClass({
displayName: 'chatWindow',
propTypes: {},
getDefaultProps: function() {
return ({
messages: 0
});
},
componentDidMount: function() {
socket = this.props.io.connect();
socket.on('value', this._messageRecieve);
},
_messageRecieve: function(messages) {
this.setState({
messages: messages
});
},
getInitialState: function() {
return ({
messages: 0
});
},
_handleSend: function(){
var newValue = parseInt(this.refs.messageBox.value) + this.props.messages;
this.setState({
messages: newValue
});
socket.emit('clientMessage', { message: newValue});
},
render: function() {
var window =
<div>
<div>{this.props.messages}</div>
<input type="text" id="messageBox" refs="messageBox"></input>
<input type="button" onClick={this._handleSend} value="send" id="send"/>
</div>;
return (window);
}
});
module.exports = chatWindow;
This is the code :
https://github.com/arian-hosseinzadeh/simple-user-list
Answers:
1) No, you don't need to specify the IP, you can even use / and it will go through the default HTTP 80 port, anyway, you can find more examples on the socket.io site.
2) Require io too, remember to add socket.io-client to your package:
var React = require('react'),
io = require('socket.io-client');
Anyway, if you want to include the client script that socket.io server provides as a static file, then remember to add it into your HTML using a <script/> tag, that way you'll have io on the global scope avoiding the require part, but well, I prefer to require it.
NOW, WHAT ABOUT...
Trying my lib: https://www.npmjs.com/package/react-socket
It will handle the socket connection on mount and disconnection on unmount (the same goes for socket event listeners), give it a try and let me know.
Here you have an example:
http://coma.github.io/react-socket/
var App = React.createClass({
getInitialState: function() {
return {
tweets: []
};
},
onTweet: function(tweet) {
var tweets = this
.state
.tweets
.slice();
tweet.url = 'https://twitter.com/' + tweet.user + '/status/' + tweet.id;
tweet.at = new Date(tweet.at);
tweet.avatar = {
backgroundImage: 'url(' + tweet.img + ')'
};
tweets.unshift(tweet);
this.setState({
tweets: tweets
});
},
renderTweet: function (tweet) {
return (
<li key={tweet.id}>
<a href={tweet.url} target="_blank">
<div className="user">
<div className="avatar" style={ tweet.avatar }/>
<div className="name">{ tweet.user }</div>
</div>
<div className="text">{ tweet.text }</div>
</a>
</li>
);
},
render: function () {
return (
<div>
<ReactSocket.Socket url="http://tweets.socket.io"/>
<ReactSocket.Event name="tweet" callback={ this.onTweet }/>
<ul className="tweets">{ this.state.tweets.map(this.renderTweet) }</ul>
</div>
);
}
});
React.render(<App/>, document.body);

Resources