how to reference itself in a component in vuejs single file component - vue.js

So here is my code:
export default {
data(){
return {
list: {}
}
},
components: {
listFields : ListFields
},
methods : {
submitForm(data){
let vm = this;
console.log(vm);
axios.post('/api/dashboard/lists/create', data)
.then(function (response) {
this.$router.push({path: 'show-list', params: {list_id: response.data.id}});
}).catch(function (error) {
console.log(error);
})
}
}
}
the problem is that inside the method where I am calling "this.$router.push" it throws an error, because this references to the function. But the problem is that I can't reference vm, because I am exporting the component. How can I solve this problem?

Your callback function is not aware of the outer context.
Either use .bind(this) or declare var that = this;
axios.post('/api/dashboard/lists/create', data)
.then(function (response) {
this.$router.push({path: 'show-list', params: {list_id: response.data.id}});
}.bind(this)).catch(function (error) {
console.log(error);
})
or
var that = this;
axios.post('/api/dashboard/lists/create', data)
.then(function (response) {
that.$router.push({path: 'show-list', params: {list_id: response.data.id}});
}).catch(function (error) {
console.log(error);
})
Update:
Since somehow nothing seems to work you can try the following: Declare a seperate method for the callback
methods : {
submitForm(data){
axios.post('/api/dashboard/lists/create', data)
.then(this.onSuccess)
.catch(function (error) {
console.log(error);
})
},
onSuccess(response) {
this.$router.push({path: 'show-list', params: {list_id: response.data.id}});
}
}

Related

Vue: executing two methods in specific order

I have a Vue application. I would like to retrieve entries (from a database) based on a userid. I have the following methods in Vue:
export default {
name: 'Entries',
data() {
return {
userid: null
};
},
methods: {
getEntries() {
this.getUserID();
console.log("userid getEntries: " + this.userid);
axios.get('/entries', this.userid)
.then((res) => {
this.entries = res.data;
console.log(this.entries);
})
.catch((error) => {
console.error(error);
});
},
getUserID() {
axios.get('/userid')
.then((res) => {
this.userid = res.data;
console.log("userid getUserId: " + this.userid );
})
.catch((error) => {
console.error(error);
});
},
},
created() {
this.getEntries();
}
};
Within the getEntries method, I'm immediately calling the getUserID function. I would assume this sets the variable userid to the value retrieved from the getUserID method.
Instead I get the following output in the browser console, in exactly this order:
userid getEntries: null
userid getUserId: user_a
Why does it print first the console output from the getEntries function? And why is this null if it first executes the getUserID method?
How could I change is so that the axios call /entries can pass the userid.
axios calls are async, if you need the userid populated before anything else is called, then you should populate before anything else is called, in mounted/created.
Then you can react to its change with a watcher. You could call getEntries when the getUserID call resolves but it's dirty and couples the two methods.
And don't forget to assign entries in data.
This will work:
export default {
name: 'Entries',
data() {
return {
userid: null,
entries: []
};
},
watch: {
userid (v) {
if (v) this.getEntries()
}
},
mounted() {
this.$nextTick(this.getUserID)
},
methods: {
getEntries() {
console.log("userid getEntries: " + this.userid);
axios.get('/entries', this.userid)
.then((res) => {
this.entries = res.data;
console.log(this.entries);
})
.catch((error) => {
console.error(error);
});
},
getUserID() {
axios.get('/userid')
.then((res) => {
this.userid = res.data;
console.log("userid getUserId: " + this.userid);
})
.catch((error) => {
console.error(error);
});
}
}
};
Using async/await
export default {
name: 'Entries',
data() {
return {
userid: null,
entries: []
};
},
watch: {
userid (v) {
if (v) this.getEntries()
}
},
mounted() {
this.$nextTick(this.getUserID)
},
methods: {
async getEntries() {
try {
const { data } = await axios.get('/entries', this.userid)
this.entries = data;
} catch (error) {
console.error(error);
}
},
async getUserID() {
try {
const { data } = await axios.get('/userid')
this.userid = data;
} catch (error) {
console.error(error);
}
}
}
};
Since getUserId is asynchronous, it doesn't return immediately. You therefore need to wait for it to return before continuing. This can be done using then but, nested Promises are a bit unpleasant to work with. A simpler option is to use async/await instead:
async getEntries() {
await this.getUserID();
console.log("userid getEntries: " + this.userid);
axios.get('/entries', this.userid)
.then((res) => {
this.entries = res.data;
console.log(this.entries);
})
.catch((error) => {
console.error(error);
});
},

Vue request can't get component data

I am trying to disable loading when the HTTP request returns an error, but it gives me this error.
Uncaught (in promise) TypeError: Cannot set property 'loading' of undefined
Code
export default {
name: 'login',
data() {
return {
loading: false, //can't be set to false on request error
}
},
methods: {
login: function () {
this.loading = true;
const { username, password } = this
this.$store.dispatch('login', { username, password }).then((resp) => {
setTimeout(() => {
this.loading = false;
}, 5000);
// this.$router.push({name: 'dashboard'})
}).catch(function (error) {
this.loading = false; // Uncaught (in promise) TypeError: Cannot set property 'loading' of undefined
console.log('error', error);
});
}
}
}
Any idea?
this represent to the object that called the function in catch method, not to the current vue component.
so either you can use var vm=this outside and use after like below.
login: function () {
this.loading = true;
var vm = this;
.....
.....
}).catch(function (error) {
vm.loading = false;
console.log('error', error);
});
}
Or use arrow method
login: function () {
.....
.....
}).catch((error) => {
this.loading = false;
console.log('error', error);
});
}
You already used arrow method with setTimeout in below code, so I guess you aware of this, just use this to fix this also
setTimeout(() => {
this.loading = false;
}, 5000);

vue updating data on create()

I am trying to update an array from my view data() inside my created hook() but my console says that the allFish is undefined. I'm not so great with vue data scoping yet and I was hoping someone could let me know if this is a diction issue, or if there's a better way to update my data on create() when receiving data from a get request and then adding it to an array inside my data.
my current app.vue
export default {
name: "App",
components: {
WebMap
},
data: () => ({
coords: {
latitude: -118,
longitude: 34,
},
date: '',
fishType: '',
allFish: []
}),
created(){
this.allFish = this.fetchFishLocations()
},
methods: {
fetchFishLocations(){
axios.get('http://localhost:3000/allFish')
.then(function (response) {
// handle success
console.log(response.data.fish);
return response.data.fish
})
.catch(function (error) {
// handle error
console.log(error);
})
},
async updateCenter() {
console.log(this.allFish) //check to see if allFish is defined
await this.getLocation();
this.addFishToDb()
},
},
};
The function which is called fetchFishLocations just returns undefined.
You'd better learn about the use of promise.
By the way, it's easier to use the arrow function
// solution 1
created(){
this.fetchFishLocations()
},
methods: {
fetchFishLocations(){
const that = this
axios.get('http://localhost:3000/allFish')
.then(function (response) {
// handle success
console.log(response.data.fish);
that.allFish = response.data.fish
})
.catch(function (error) {
// handle error
console.log(error);
})
}
}
// solution 2
created(){
const that = this
this.fetchFishLocations()
.then(function (response) {
// handle success
console.log(response.data.fish);
that.allFish = response.data.fish
})
.catch(function (error) {
// handle error
console.log(error);
})
},
methods: {
fetchFishLocations(){
return axios.get('http://localhost:3000/allFish')
}
}
You need fill allFish in axios->then method.
...
created() {
this.fetchFishLocations();
},
methods: {
fetchFishLocations(){
axios.get('http://localhost:3000/allFish')
.then(function (response) {
// handle success
console.log(response.data.fish);
this.allFish = response.data.fish;
})
.catch(function (error) {
// handle error
console.log(error);
})
},
}
...

aixos reponse data can not assign to Vue instance's data

In my vue.js project, i get an array data by axios, and want to assign to bookList variable, but failed, bookList still equal to [], could you tell me why?
export default {
...
data () {
return {
bookList: []
}
},
mounted: function() {
this.$nextTick(function(){
this.viewBooks();
});
},
methods: {
viewBooks: function() {
axios.get('/books.json')
.then(res=>{
this.bookList = res.data.bookList;
})
.catch(error=>{
console.log(error);
});
}
}
The callback is on a different scope...this should work
methods: {
viewBooks: function() {
let self = this;
axios.get('/books.json')
.then(res=>{
self.bookList = res.data.bookList;
})
.catch(error=>{
console.log(error);
});
}
There's also a different answer here

TypeError: this.$set is not a function

Hi I am geting this error:
Uncaught (in promise) TypeError: this.$set is not a function
And here is the code:
export default {
data: function() {
return { movies: '' }
},
ready: function() {
this.showMovies()
},
methods: {
showMovies: function() {
this.$http.get(config.api.url + '/movies').then(function (response) {
this.$set('movies', response.data)
})
}
}
}
The reason why this.$set is not a function in your example code is because this doesn't refer to Vue ViewModel instance anymore.
To make code you've posted working, you need to keep reference to it:
export default {
data: function() {
return { movies: '' }
},
ready: function() {
this.showMovies()
},
methods: {
showMovies: function() {
var vm = this; // Keep reference to viewmodel object
this.$http.get(config.api.url + '/movies').then(function (response) {
vm.$set('movies', response.data)
})
}
}
}
in the callback function you're loosing the Vue instance (this), this could be solved by using the arrow function ()=>{...} :
this.$http.get(config.api.url + '/movies').then((response)=> {
this.$set('movies', response.data)
})
or binding the callback to this :
this.$http.get(config.api.url + '/movies').then(function (response) {
this.$set('movies', response.data)
}).bind(this)