How Can I pass params with an API client to vue-head? - vue.js

I am passing params from my API to vue-head but every time I do that it send me undefined in the head this is the code:
export default {
data: () => ({
errors: [],
programs: [],
}),
methods: {
getProgram() {
this.api.http.get(`videos/program/${this.programSlug}`)
.then(response => {
this.programs = response.data
})
.catch(error => {
this.errors = error
});
}
},
head: {
title: function() {
return {
inner: this.programs.name,
separator: '|',
complement: 'Canal 10'
};
}
}
}
any idea what I am doing wrong with my code??

First verify you are fetching the information correctly. Use console log and go to network tab and verify you are fetching the data correct, you might have to comment out vue-head. But what I think is that the problem might be due to vue-head rendering before the api call finishes then no data is being passed.
If you are using vue-router this can be easily solved with beforeRouteEnter() hook. But if not! apparently vue-head has an event that you can emit to update the component after render.
I haven't tried this but it should work. you can add the function below to your methods and call it after the promise is resolved i.e in the then closure.
methods: {
getProgram() {
this.api.http.get(`videos/program/${this.programSlug}`)
.then(response => {
this.programs = response.data
this.$emit('updateHead')
})
.catch(error => {
this.errors = error
});
}
}

Related

A method not working in Vue.js and can't figure out what the problem is

From the code below, I'm sending email using EmailJs library and the alert method get's executed after submitting but the change method doesn't. What I'm I missing?
Error message on the console is
Uncaught (in promise) TypeError: Cannot read property 'change' of undefined
at app.js:2755
My Script
<script>
import emailjs from "emailjs-com";
export default {
data() {
return {
flash: false,
};
},
methods: {
sendEmail: (e) => {
emailjs
.sendForm(
"service_k9mhh",
"template_epghgfh",
e.target,
"user_w9U76tg77yhcggh"
)
.then(
(result) => {
console.log("SUCCESS!", result.status, result.text);
alert("Message Sent Successfully")
this.change();
},
(error) => {
console.log("FAILED...", error);
}
);
// Reset form field
},
change(){
this.flash = true;
}
},
};
</script>
Without arrow functions as shown below, It still throws the same error.
methods: {
sendEmail: function (e) {
emailjs
.sendForm(
"service_",
"template_",
e.target,
"user_"
)
.then(
function (result) {
console.log("SUCCESS!", result.status, result.text);
this.change();
},
function (error) {
console.log("FAILED...", error);
}
);
},
change: function () {
this.flash = true;
}
The problem is that in arrow functions this does not refer to the Vue instance so this.change is not defined there.
Read this:
https://v2.vuejs.org/v2/guide/instance.html#Data-and-Methods
Okay so you and eldo were both half right. You need to use a regular function syntax when declaring a method, and an arrow function in any nested .then's.
Using an arrow function in your then and catch handler's ensures that 'this' remains a reference to the Vue instance.
Your method wants to look like this:
sendEmail(e) {
emailjs
.sendForm("service_", "template_", e.target, "user_")
.then((result) => {
console.log("SUCCESS!", result.status, result.text);
this.change();
})
.catch((error) => {
console.log("FAILED...", error);
});
},

How can i pass parameters from method to action in vuejs vuex

I have to files with this code:
Users.vue
methods: {
obtenerUsuarios() {
console.log('Obtener Usuarios')
this.$store
.dispatch('auth/getValidToken')
.then((data) => {
console.log(data). // Console First Message
this.$store
.dispatch('user/fetchUsers', data)
.then((response) => {
this.items = response.data
})
.catch((error) => {
console.log(error)
})
})
.catch((error) => {
console.log('Error: ' + error)
})
},
},
Console Firsts Mesagge show me a json web token in console that is ok.
When i dispatch 'user/fetchUsers in
user.js
export const actions = {
fetchUsers({ jwt }) {
console.log('Action JWT:' + jwt) //Second console.log
return UserService.getUsers(jwt)
},
}
The second messaje show me: Action JWT:undefined in the console
if i change the line two to
fetchUsers(jwt) {
The second messaje show me: Action JwT:[object Object]
I need to pass a json web token from Users.vue method to fetchUsers action y user.js
I will to appreciate any help
Jose Rodriguez
Your action method currently declares the data in the first argument (and no second argument), but actions receive the Vuex context as its first argument. The data payload is in the second argument:
const actions = {
//fetchUsers(data) {} // DON'T DO THIS (1st arg is for context)
fetchUsers(context, data) {}
}

Set data propert value from sequelize promise vue

I am using Vue, Electron and Sequelize, when I npm run electron:serve, sequelize promise doesn't return anything, data property won't set or show unless I save the code again to refresh the existing window:
<script>
export default {
data () {
users : [],
}
},
created () {
console.log('created')
this.fetchData();
},
methods: {
fetchData () {
let self = this
let allUsers = db.User.findAll({
attributes: ['id', 'first_name', 'last_name', 'email', 'password'],
raw : true
}).then(res => {
console.log('then working');
self.users = res;
}).catch(err => {
console.log('there was an error' + err)
})
console.log('fetchData method called' + allUsers)
},
}
</script>
I can see the fetchData() is being called but nothing show after .then( ... unless page is saved and refreshed.
Please take a look at the component data section. It doesn't have users:
data () {
dialog: false,
}
All properties that should be reactive are declared in the data section of a component.

How can I pass the value from my API to my head tittle with vue-head?

I am using vue-head in website because of I have to pass the name of the program to the html head, and the inf. it is coming from an API, so I make the request but every time I try to pass the name it send me error this the code:
export default {
data: () => ({
errors: [],
programs: [],
firstVideo: {},
vidProgram: {}
}),
},
created() {
//do something after creating vue instance
this.api = new ApiCanal({})
this.getProgram()
},
methods: {
getProgram() {
this.api.http.get(`videos/program/${this.programSlug}`)
.then(response => {
this.programs = response.data
this.firstVideo = response.data[0]
this.vidProgram = response.data[0]['program']
})
.catch(error => {
this.errors = error
});
}
},
head: {
//this is the inf. for the head
title: {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
}
}
}
I will really appreciate if you can help me with this issue
If you want to use properties of your Vue object/component in the title there, you need to make it a function, as currently this refers to the object creating your Vue component (probably the global window object).
head: {
title: function() {
return {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
};
}
}

Unit testing HTTP request with Vue, Axios, and Mocha

I'm really struggling trying to test a request in VueJS using Mocha/Chai-Sinon, with Axios as the request library and having tried a mixture of Moxios and axios-mock-adaptor. The below examples are with the latter.
What I'm trying to do is make a request when the component is created, which is simple enough.
But the tests either complain about the results variable being undefined or an async timout.
Am I doing it right by assigning the variable of the getData() function? Or should Ireturn` the values? Any help would be appreciated.
Component
// Third-party imports
import axios from 'axios'
// Component imports
import VideoCard from './components/VideoCard'
export default {
name: 'app',
components: {
VideoCard
},
data () {
return {
API: '/static/data.json',
results: null
}
},
created () {
this.getData()
},
methods: {
getData: function () {
// I've even tried return instead of assigning to a variable
this.results = axios.get(this.API)
.then(function (response) {
console.log('then()')
return response.data.data
})
.catch(function (error) {
console.log(error)
return error
})
}
}
}
Test
import Vue from 'vue'
import App from 'src/App'
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
let mock = new MockAdapter(axios)
describe('try and load some data from somewhere', () => {
it('should update the results variable with results', (done) => {
console.log('test top')
mock.onGet('/static/data.json').reply(200, {
data: {
data: [
{ id: 1, name: 'Mexican keyboard cat' },
{ id: 2, name: 'Will it blend?' }
]
}
})
const VM = new Vue(App).$mount
setTimeout(() => {
expect(VM.results).to.be.null
done()
}, 1000)
})
})
I am not sure about moxios mock adaptor, but I had a similar struggle. I ended up using axios, and moxios, with the vue-webpack template. My goal was to fake retreiving some blog posts, and assert they were assigned to a this.posts variable.
Your getData() method should return the axios promise like you said you tried - that way, we have some way to tell the test method the promise finished. Otherwise it will just keep going.
Then inside the success callback of getData(), you can assign your data. So it will look like
return axios.get('url').then((response) {
this.results = response
})
Now in your test something like
it('returns the api call', (done) => {
const vm = Vue.extend(VideoCard)
const videoCard = new vm()
videoCard.getData().then(() => {
// expect, assert, whatever
}).then(done, done)
)}
note the use of done(). That is just a guide, you will have to modify it depending on what you are doing exactly. Let me know if you need some more details. I recommend using moxios to mock axios calls.
Here is a good article about testing api calls that helped me.
https://wietse.loves.engineering/testing-promises-with-mocha-90df8b7d2e35#.yzcfju3qv
So massive kudos to xenetics post above, who helped in pointing me in the right direction.
In short, I was trying to access the data incorrectly, when I should have been using the $data property
I also dropped axios-mock-adaptor and went back to using moxios.
I did indeed have to return the promise in my component, like so;
getData: function () {
let self = this
return axios.get(this.API)
.then(function (response) {
self.results = response.data.data
})
.catch(function (error) {
self.results = error
})
}
(Using let self = this got around the axios scope "problem")
Then to test this, all I had to do was stub the request (after doing the moxios.install() and moxios.uninstall for the beforeEach() and afterEach() respectively.
it('should make the request and update the results variable', (done) => {
moxios.stubRequest('./static/data.json', {
status: 200,
responseText: {
data: [
{ id: 1, name: 'Mexican keyboard cat' },
{ id: 2, name: 'Will it blend?' }
]
}
})
const VM = new Vue(App)
expect(VM.$data.results).to.be.null
VM.getData().then(() => {
expect(VM.$data.results).to.be.an('array')
expect(VM.$data.results).to.have.length(2)
}).then(done, done)
})