Vue ajax request isn't updating data - vue.js

I'm new to Vue but from my research this should be working. the console keeps showing users as null but when i look at the response of the request it has the users. I thought the => was supposed to update the vue instance.
...
data () {
return {
users: null,
}
},
...
methods: {
getUsers () {
this.$axios.get('/api/users')
.then(r => {
this.users = r.data
})
console.log(this.users)
},
},
...
created () {
this.getUsers()
this.users.forEach(function (u) {
...
})
}

If you want to loop through the collection of users, you have to first wait until they are actually available - you can use then callback for it:
export default {
data () {
return {
users: [],
}
},
methods: {
getUsers () {
return this.$axios.get('/api/users')
.then(r => {
this.users = r.data
})
.catch(error => console.log(error));
},
},
created () {
this.getUsers().then(() => {
this.users.forEach(function (u) {
...
})
})
}
}
Rather than converting returned collection from within vue component it would be better to return it formatted with the response - using plain php you could achieve it with array_map - here I'm using an array of User models as an example:
$users = array_map(function (User $user) {
return [
'value' => $user->id,
'name' => $user->name,
];
}, $users);
The above will return something like:
[
[
'value' => 1,
'name' => 'Jon Doe',
],
[
'value' => 2,
'name' => 'Jane Doe',
],
]

You can move your users processing to a watcher:
...
data () {
return {
users:[],
}
},
watch: {
users (users) {
if( ! this.users.length )
return;
this.users.forEach(function (u) {
...
})
},
},
...
methods: {
getUsers () {
this.$axios.get('/api/users')
.then(r => {
this.users = r.data
})
console.log(this.users)
},
},
...
created () {
this.getUsers()
}
Or if you prefer a one time processing, make it a method and call that method in the axios then():
...
methods: {
getUsers () {
this.$axios.get('/api/users')
.then(r => {
this.users = r.data
this.processUsers();
})
console.log(this.users)
},
processUsers() {
// do something with this.users
},
},

Related

Vue.js with Axios use data from other method

I have a external api which returns a json of a user with some attributes like username. I want to use this username in my vue methods as a url parameter and defined the function getUser(). My problem is that the parameter keeps undefined
Here is my code
<script>
import Axios from 'axios-observable'
export default {
data () {
return {
appointments: {},
event_counter: 0,
user: ''
},
methods: {
getUser: function () {
Axios
.get('http://127.0.0.1:5000/users/get_user')
.subscribe(response => { this.user = response.data.username })
},
getAppointments: function () {
Axios
.get('http://127.0.0.1:5000/appointments/get_appointments?user=' + this.user)
.subscribe(response => { this.appointments = response.data })
},
fetchData: function () {
setInterval(() => {
this.getAppointments()
}, 150000)
}
},
mounted () {
//this.user = this.getUser()
this.getUser()
this.fetchData()
},
created () {
//this.user = this.getUser()
this.getUser()
this.getAppointments()
}
}
</script>
I tried some variants with return response.data or data: this.getUser() etc. Obtaining the user in template with {{ user }} works fine but isn't helpful. I don't have any syntax or runtime error from vue/electron-vue
Any idea?
Finally got a solution!
<script>
import Axios from 'axios'
export default {
data () {
return {
appointments: {},
event_counter: 0,
user: 'test'
}
},
methods: {
getUser: function () {
return Axios
.get('http://127.0.0.1:5000/users/get_user')
.then(response => {
this.user = response.data.username
return this.user
})
},
getAppointments: function () {
this.getUser()
.then(data => {
let url = 'http://127.0.0.1:5000/appointments/get_appointments?user=' + data
Axios
.get(url)
.then(response => { this.appointments = response.data })
})
},
fetchData: function () {
setInterval(() => {
this.getAppointments()
}, 150000)
}
},
mounted () {
this.fetchData()
},
created () {
this.getAppointments()
}
}
</script>
The solution was to change the call of the getUser() and retrieve the date in the arrow function block .then(data =>).
The answer of #loan in this Issue give me the hint: How to set variable outside axios get.
Thanks a lot to all.
<script>
import Axios from 'axios-observable'
export default {
data () {
return {
appointments: {},
event_counter: 0,
user: ''
},
computed: {
updatedUrl: {
return `http://127.0.0.1:5000/appointments/get_appointments?user=${this.user}`
}
},
methods: {
forceGetUsername() {
return this.user
},
getUser: function () {
Axios
.get('http://127.0.0.1:5000/users/get_user')
.subscribe(response => { this.user = response.data.username })
},
getAppointments: function () {
console.log(updatedUrl)
Axios
.get(updatedUrl)
.subscribe(response => { this.appointments = response.data })
},
// Below can remain the same
}
</script>
So it seems the url is being cached and not updated once created. So I added new function to ensure the latest value is being returned. Not very ideal.
Added the URL to computed property. If this doesn't work then I am lost as well :(

Vuex Store does not update [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
I've been refactoring my Vue SPA and one of the changes I was wanting to make has been the removal of manually importing "Store" in every component that needs it and instead uses the "this.$store.dispatch('module/update', data)", but it doesn't update the store like "Store.dispatch('module/update', data)" used to in the past.
methods: {
update() {
let office = {
id: this.office.id,
name: this.name,
description: this.description,
abbreviation: this.abbreviation
};
this.$http.post('/api/office/update', office).then(function(result) {
Store.dispatch('offices/update', result.data);
this.$router.push({ path: '/settings/offices' });
}).catch((error) => {
this.$router.push({ path: '/settings/offices' });
});
}
}
export const Offices = {
namespaced: true,
state: {
all: []
},
mutations: {
ADD_OFFICE: (state, offices) => {
offices.forEach(office => {
state.all.push(office);
});
},
DELETE_OFFICE: (state, id) => {
state.all.splice(state.all.map((office) => { return office.id }).indexOf(id), 1);
},
UPDATE_OFFICE: (state, data) => {
Object.assign(state.all.find((office) => office.id === data.id), data);
}
},
actions: {
get(context) {
Axios.get('/api/office/all').then((response) => {
context.commit('ADD_OFFICE', response.data);
});
},
create(context, office) {
context.commit('ADD_OFFICE', office);
},
update(context, data) {
context.commit('UPDATE_OFFICE', data);
},
delete(context, id) {
context.commit('DELETE_OFFICE', id);
}
}
}
I expected it to update the store as importing it manually does.
Mutations should be immutable to make data reactive
mutations: {
ADD_OFFICE: (state, offices) => {
state.all = state.all.concat(offices)
},
DELETE_OFFICE: (state, id) => {
state.all = state.all.filter(office => office.id != id)
},
UPDATE_OFFICE: (state, data) => {
const officeIndex = state.all.findIndex(office => office.id === data.id)
const newObj = Object.assign(state.all[officeIndex], data)
state.all = [
...state.all.slice(0, officeIndex),
newObj,
...state.all.slice(officeIndex + 1)
]
}
},

Cannot assign axios response value to a variable - vue.js

I created an array lists that contains a few strings.
Now I want to loop through lists (i.e., in getSubs()) and make an Axios request. This request should contain one string from lists each time.
My code:
computed: {
subscribers: {
get() {
return this.$store.state.subscribers;
},
set(value) {
this.$store.commit('updateSubscribers', value);
},
},
},
methods: {
getLodzkie() {
axios
.get(`correct_domain/lodzkietargi/get`)
.then((response) => {
this.subscribers = [];
this.subscribers.push.apply(this.subscribers, response.data)
})
.catch(function(error) {
console.log(error);
})
},
getSubs() {
function getSub(value) {
axios
.get(`correct_domain/${value}/get`)
.then((response) => {
this.subscribers.push.apply(this.subscribers, response.data)
})
.catch(function(error) {
console.log(error);
});
console.log(value);
}
this.lists.forEach(function(entry) {
getSub.call(null, entry);
});
},
getLodzkie() works beautifully
Thank You a lot #ourmandave. That helped me perfectly.
Rewrote function below:
getSubs() {
let listsReqs = this.lists.map(list => {
return axios.get(`correct_domain/${list}/get`);
});
axios.all(listsReqs)
.then(axios.spread((...responses) => {
responses.forEach(res => this.subscribers.push.apply(this.subscribers, res.data));
})
)},

function not defined upon requesting via axios in vue

I am trying to make an axios call and it works fine but when I call the function from the scope it returns me
loadData is undefined.
import vSelect from 'vue-select';
export default {
props : [],
data : () => {
return {
assets : [],
folders : [],
parent_id : 0,
moveParentId : null,
selectedAsset: {},
parentStack : [],
searchTerm : '',
};
},
components: {
vSelect,
},
created() {
this.loadData(this.parent_id);
this.createFolder();
},
methods : {
loadData(parentId) {
axios
.get(
'/api/assets',
{
params: {
parent_id: parentId,
},
},
)
.then((response) => {
this.parentStack.push(parentId);
this.assets = response.data;
})
.catch((error) => {
if (error.response.status === vue.$options.HTTP_STATUS.UNPROCESSABLE_ENTITY) {
}
});
},
createFolder() {
$('#create-folder-button').on('click', function (e) {
let form = $('#create-folder').find('form'),
namefield = form.find('input#name'),
name = namefield.val(),
action = '/assets',
errorelem = form.find('#create-error');
axios
.post(action, {
name: name,
type: 1,
})
.then(() => {
$('#create-folder').modal('hide');
loadData(this.parent_id); //ERROR OCCURS HERE.
}, function (error) {
if (error.response != null) {
if (error.response.status == vue.$options.HTTP_STATUS.UNPROCESSABLE_ENTITY) {
errorelem.html(error.response.status).show();
}
}
});
});
}
this is my code.

pass computed property as method parameter?

So I have a store with values:
export const store = new Vuex.Store({
state: {
selectedGradeId: null,
},
getters:{
selectedGradeId: state => {
return state.selectedGradeId
},
},
mutations:{
SET_SELECTED_GRADE_ID(state, gradeid){
state.selectedGradeId = gradeid
},
CLEAR_SELECTED_GRADE_ID(state){
state.selectedGradeId = null
},
},
actions:{
loadStudentsForGrade (gradeId) {
return new Promise((resolve, reject) => {
axios.get('/students/'+gradeId)
.then((response)=>{
... do stuff
resolve(response)
}, response => {
reject(response)
})
})
},
}
})
and inside my component i basically have a select that loads the student list for the particular grade:
<select id="grades" name="grades" v-model="selectedGradeId" #change="loadStudentsForGrade(selectedGradeId)"
methods: {
loadStudentsForGrade(gradeId) {
this.$store.dispatch('loadStudentsForGrade', {gradeId})
.then(response => {
}, error => {
})
},
},
computed: {
selectedGradeId: {
get: function () {
return this.$store.getters.selectedGradeId;
},
set: function (gradeId) {
this.$store.commit('SET_SELECTED_GRADE_ID', gradeId);
}
},
}
when the 'loadStudentsForGrade' method is called in my component, it takes 'selectedGradeId' as a parameter, which is a computed property.
Now the problem I have is that inside my store, the action 'loadStudentsForGrade' gets an object( i guess computed?) instead of just the gradeid
object i get is printed to console:
{dispatch: ƒ, commit: ƒ, getters: {…}, state: {…}, rootGetters: {…}, …}
The first parameter of your action is the store, and the second the payload.
so you should do :
actions:{
// here: loadStudentsForGrade (store, payload) {
loadStudentsForGrade ({ commit }, { gradeId }) {
return new Promise((resolve, reject) => {
axios.get('/students/'+gradeId)
.then((response)=>{
//... do stuff
//... commit('', response);
resolve(response)
}, response => {
//... commit('', response);
reject(response)
})
})
},
}
Related page in the docs :
https://vuex.vuejs.org/en/actions.html#dispatching-actions