Reputation: 53
I have a list in utils that I use it almost everywhere and it only has text
variable in each object.
In one of my components, I need to add done
variable to each item in that list so I can toggle them. I can see that the variable is added, but whenever I toggle it, the view does not get updated.
const arrayFromUtils = [{
text: "Learn JavaScript"
},
{
text: "Learn Vue"
},
{
text: "Play around in JSFiddle"
},
{
text: "Build something awesome"
}
];
new Vue({
el: "#app",
data: {
todos: arrayFromUtils
},
mounted() {
this.todos.forEach(item => (item.done = false));
},
methods: {
toggle: function(todo) {
todo.done = !todo.done
console.log('toggled item: ', todo);
}
}
})
.red {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="todo in todos" :key="todo.text">
<div @click="toggle(todo)" :class="{ red: todo.done }">
{{ todo.text }}
</div>
</div>
</div>
I can see that done
variable gets updated when toggling an item, but the view does not get updated. What am I doing wrong?
Upvotes: 0
Views: 41
Reputation: 1904
You are adding a property to each of your todos items. To make it reactive, you need to use this.$set
. Take a look at the documention about changes detection caveats.
Your mounted
function should be:
mounted() {
this.todos.forEach(item => this.$set(item, "done", false));
}
Upvotes: 1
Reputation: 53
Hey it's problem with Vue Reactivity https://v2.vuejs.org/v2/guide/reactivity.html
You are changing item in array if you want to do this you need to use vm.$set or map whole array.
If you do this in your way vue can't detect if something changed that will be posible in vue3 :)
mounted() {
this.todos.map(item => ({...item, done: false});
}
Upvotes: 0