I have a problem on my last Vue JS page. I think I am totally wrong.
Let me explain, I have a button which make an API GET call to the backend and I got an array as a response from the API.
When I received this array, I push data in this.templates
.
I have a v-for on this array :
<v-flex
xs12
md4
v-for="item of templates"
:key="item._id"
>
with inside :
<v-card elevation="10" :loading="loadingTemplates[item._id]">
When I received the response, v-card are correctly displayed with loading true. After this, I have a second POST request for each element, and when I received the response, I set to false the value :
console.log(`Response for ${element._id} and ${element.loading}`);
this.loadingTemplates[element._id] = false;
Log is OK, i have ID and true value. I set false, but loading is still displayed....
Why ?
Maybe I need to use json object for templates, but i don't know how. TO resume : GET Request ==> Get Array with x jobs POST Request for x jobs ==> With v-simple-table displayed.
CodePudding user response:
As @stellr42
mentioned in his comment, Vue 2 has some limitations on reactivity when it comes to arrays. You can have a look into this official documentation
.
Vue cannot detect the following changes to an array :
- When you directly set an item with the index, e.g.
this.loadingTemplates[element._id] = false
- When you modify the length of the array, e.g.
this.loadingTemplates.length = newLength
Demo as per the above statements :
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
loadingTemplates: [true, true, false, true]
},
mounted() {
this.loadingTemplates[1] = false; // Not updating
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li v-for="item_id in [0, 1, 2, 3]">{{ loadingTemplates[item_id] }}</li>
</ul>
</div>
Hence, To update and make it reactive - You also have to trigger state updates in the reactivity system.
Working Demo :
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!',
loadingTemplates: [true, true, false, true]
},
mounted() {
this.$set(this.loadingTemplates, 1, false);
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li v-for="item_id in [0, 1, 2, 3]">{{ loadingTemplates[item_id] }}</li>
</ul>
</div>