Get data attributes from v-link - javascript

Sure it's a easy thing but at the moment i just can't get it to work. I have a component called posts.vue which includes this link in the template:
<template>
<a v-link="{ name: 'post', params: { slug: post.post_name }}" v-postid="{ post.ID }"><h2>{{ post.post_title }}</h2></a>
</template>
My Routes are set up like this:
'/post/:slug': {
name: 'post',
component: require('./components/post.vue')
}
Now my question is how can i get the postid data attribut in my post.vue component which gets loaded after the route matches.
In my old jquery days i would do it like that:
$('a.link').click(function() {
var attr = $(this).data('post-id');
}
(Just to showcase what i meant)
Thanks for any help guys! Vue.js is great so far, enjoy it alot.

Assuming you have a post object inside your component that you set with ajax after the route is loaded
data: function() {
return {
post: {}
}
}
and
route: function() {
data: function() {
var resource = fetchPost(this.$route.params.slug)
this.$set('post', resource)
}
}
You can access the post.id everywhere in your component like this this.$data.post.id
The v-postid directive is not required for that.

Related

nuxt.js get default head in vue.js component

I am trying to get the head object that is configured by nuxt.config.js in a vue layout. In order to show the same title in an app bar as the page title.
I know that you can alter the page title with the head function in a vue component. But is it also possible to retrieve this information somehow?
<script>
export default {
data () {
return {
title: head.titleTemplate // possible?
}
},
head () {
// here it is possible to change it but how about getting it?
}
}
</script>
Another approach could be to get some data out of an page in the nuxt.config.js. But I think this is not how the hierarchy is structured.
Thanks for you help I am just starting to use javascript to code a website :)
(If I understand you correctly) You can use the changed callback to keep track of the latest meta info used (and thus the title).
Example:
head() {
return {
changed: (info) => {
this.title = info.title;
console.log(info, info.title);
},
};
},
data() {
return {
title: '',
};
},
In nuxt.config.js before export I have setted variable with a string of the title.
Then added it to the head section and create a new env section:
https://nuxtjs.org/api/configuration-env/
const title = `Site title`
export default {
head: {
title
},
env: {
title
}
}
This how I'm getting the title in any Vue component:
export default {
computed: {
title () {
return process.env.title
}
},
}
This helps you to keep your original title in process.env.title, even if you will want to change head.title dynamically.
Did anyone found a better solution maybe? :)

Vue.js undefined error on object value when loaded and rendered

OK. I'm not a total newbie and do have some Vue xp but this is bugging me. What really obvious thing am I missing.
I have an object loaded via an ajax call inside a mounted method:
job: {
"title": "value",
"location": {
"name":"HONG KONG"
}
}
When I call {{ job.title }} all good. When I call {{ job.location.name }} I have an undefined error but the value renders. When I call {{ job.location }} I get the json object so it is defined.
Aaargh! I'm sure it's really simple but can't possibly see why this isn't as straight forward as it should be.
// Additional
This is my entire Vue class
const router = new VueRouter({
mode: 'history',
routes: []
});
const app = new Vue( {
router,
el: '#app',
data: {
job: {}
},
mounted: function () {
var vm = this
jQuery.ajax({
url: 'https://xxx' + this.jobId,
method: 'GET',
success: function (data) {
vm.job = data;
},
error: function (error) {
console.log(error);
}
});
},
computed: {
jobId: function() {
return this.$route.query.gh_jid
}
}
})
When your component renders it tries to get value from job.location.name but location is undefined before ajax request is completed. So I guess error is kind of Cannot read property 'name' of undefined.
To fix this you can define computed property locationName and return, for example, empty string when there is no loaded job object yet:
computed:{
//...
locationName() {
return this.job.location ? this.job.location.name : '';
}
}
Or you can define computed for location and return empty object if there is no location, or you can just add empty location object to your initial data(if you are sure that your API response always has location) like job: { location: {}} all ways will fix your issue.
Also there is a way to fix it with v-if directive in your template:
<div v-if="job.location">
{{ job.location.name }}
<!-- other location related stuff -->
</div>
An ES6 solution for you:
computed: {
getJobName(){
return this.job?.location.name
}
}
Optional Chaining

Vuejs - Render raw html links to <router-link>

I;m new to VueJS and I'm making some weird experiments. I build a backend service using python/flask and this backend provide me a string of html code with many tags inside, I want to render this inside my Vue app, I have a method for calling the backend that looks like this:
async execute (method, resource, data) {
return client({
method,
url: resource,
data: data
}).then(async req => {
return req.data.html
})
},
callBack (id) {
console.log(id)
return this.execute('post', '/content/', {body: { 'id': id }})
}
And in the .vue file I have:
export default {
data () {
return {
loading: false,
launch: [],
html: 'none',
page: this.$route.params.article
}
},
beforeMount () {
console.log('beforeee')
this.html = api.callBack(this.page)
},
methods: {
async launch () {
this.launch = ''
this.html = await api.callBack(this.page)
}
}
}
so when I call the launch function it populates this.html, and this html variable lives in a v-html.Everything seems to work i get the html and render it in de container but the links are broken, the links should point at the same app something like #/test/linkvalue, but as they are tags, and in vue you have to use they doesn't work.
There is a way to achieve this "dynamic re route" or I'm doing something too weird?
The links are plenty, since they are scraped from the web, so manually parsing is not an option.
JSFiddle
Thanks in advance for your help
Also, you shouldn't return the raw html. Just return the paths for the routes and then loop the paths and create links that way.
You can use the v-html vue directive to output raw html.
https://jsfiddle.net/eywraw8t/66262/
new Vue({
el: "#app",
data: {
rawhtml: "<h1 style='color: red;'>Hi, I am raw html.</h1>"
},
methods: {
}
})
<div id="app">
<div v-html="rawhtml"></div>
</div>

ember set component data from application controller

I am new to Ember and trying to figure out how the data routing works. I have a 'page-notices' component and template thats included in my application.hbs file. It handles showing error or other notifications to users. I cannot figure out how to set the data inside the component from the application controller.
When a user triggers a logout action in application controller, I send it to the server via ajax json request and then need to update the page-notices component if there was an error returned. What does the page-notices controller need to look like to get this done? Am I asking the wrong question and shouldn't be using the controller for this?
//app/templates/application.hbs
{{app-header}}
<div id="pagecontent">
{{page-notices}}
<div id="wrapper">
{{outlet}}
<div class="push"></div>
</div>
</div>
{{app-footer}}
//app/controllers/application.js
import Ember from 'ember';
import ENV from '/config/environment';
var $ = Ember.$;
export default Ember.Controller.extend({
session: Ember.inject.service('session'),
pagenotices: Ember.inject.controller("page-notices")
actions: {
logout: function() {
var self = this;
$.ajax({
dataType: "json",
method: 'GET',
url: ENV.APP.apiHost,
data: {p: 'logout'},
success: function( response ){
if( response.success || (response.loggedin == false) ){
self.get('session').invalidate();
self.transitionToLoginRoute();
} else {
self.get('pagenotices').set('pageerrors', response.error);
self.get('pagenotices').set('pageerrorsview', '');
}
}
});
},
},
transitionToLoginRoute: function() {
this.transitionToRoute('login');
},
});
//app/templates/components/page-notices.js
<div id="pagenotices" class="{{pagenoticeview}}">
<div id="pageerrors" class="error centered {{pageerrorsview}}">{{pageerrors}}</div>
<div id="pagemessages" class="notice centered {{pagemessagesview}}">{{pagemessages}}</div>
</div>
//app/components/page-notices.js
import Ember from 'ember';
import ENV from '/config/environment';
const { inject: { service }, Component } = Ember;
export default Component.extend({
pagenoticeview: 'hide',
pageerrors: '',
pageerrorsview: 'hide',
pagemessages: '',
pagemessagesview: 'hide',
});
I did not quite understand why you injected page-notices controller to application controller; because you have already put page-notices component directly to application.hbs. I might be wrong but I got the sense that you are confusing a controller and a component.
Anyway,the following should work.
Remove pagenotices: Ember.inject.controller("page-notices") this; since we have no work with pagenotices controller as I explained above.
Change the else part in ajax handler of logout action within application.js as follows:
self.set('pageerrors', response.error);
self.set('pageerrorsview', '');
So that the corresponding attributes are directly saved to application controller itself.
Pass the corresponding attributes to page-notices component from within application.hbs with
{{page-notices pageerrors=pageerrors pageerrorsview=pageerrorsview}}
Declare the initial values of pageerrors and pageerorsview within application.js and remove them from page-notices component if you want. I mean declarations of pageerrors: '', pageerrorsview: 'hide'
This should work if I got what you are asking right, best regards.

Vue.js - Global Data from AJAX Call

I'm giving Vue.js a try and so far I'm loving it because it's much simpler than angular. I'm currently using vue-router and vue-resource in my single page app, which connects to an API on the back end. I think I've got things mostly working with a the primary app.js, which loads vue-router and vue-resource, and several separate components for each route.
Here's my question: How do I use props to pass global data to the child components when the data is fetched using an asynchronous AJAX call? For example, the list of users can be used in just about any child component, so I would like the primary app.js to fetch the list of users and then allow each child component to have access to that list of users. The reason I would like to have the app.js fetch the list of users is so I only have to make one AJAX call for the entire app. Is there something else I should be considering?
When I use the props in the child components right now, I only get the empty array that the users variable was initialized as, not the data that gets fetched after the AJAX call. Here is some sample code:
Simplified App.js
var Vue = require('vue');
var VueRouter = require('vue-router')
Vue.use(VueRouter);
var router = new VueRouter({
// Options
});
router.map({
'*': {
component: {
template: '<p>Not found!</p>'
}
},
'/' : require('./components/dashboard.js'),
});
Vue.use(require('vue-resource'));
var App = Vue.extend({
ready: function() {
this.fetchUsers();
},
data: function() {
return {
users: [],
};
},
methods: {
fetchUsers: function() {
this.$http.get('/api/v1/users/list', function(data, status, response) {
this.users = data;
}).error(function (data, status, request) {
// handle error
});
}
}
});
router.start(App, '#app')
Simplified app.html
<div id="app" v-cloak>
<router-view users = "{{ users }}">
</router-view>
</div>
Simplified dashboard.js
module.exports = {
component: {
ready: function() {
console.log(this.users);
},
props: ['users'],
},
};
When dashboard.js gets run, it prints an empty array to the console because that's what app.js initializes the users variable as. How can I allow dashboard.js to have access to the users variable from app.js? Thanks in advance for your help!
p.s. I don't want to use the inherit: true option because I don't want ALL the app.js variables to be made available in the child components.
I believe this is actually working and you are being misled by the asynchronous behavior of $http. Because your $http call does not complete immediately, your console.log is executing before the $http call is complete.
Try putting a watch on the component against users and put a console.log in that handler.
Like this:
module.exports = {
component: {
ready: function() {
console.log(this.users);
},
props: ['users'],
watch: {
users: {
handler: function (newValue, oldValue) {
console.log("users is now", this.users);
},
deep: true
}
}
}
};
In the new version of Vue 1.0.0+ you can simply do the following, users inside your component is automatically updated:
<div id="app" v-cloak>
<router-view :users="users"></router-view>
</div>

Categories

Resources