Reputation: 10422
I have a vue.js item in my page that tracks changes made to a form. It looks like this:
var changes_applied = [];
var changes_applied_block = new Vue({
name: "ChangesApplied",
el: '#changes-applied',
data: {
items: changes_applied
},
methods: {
remove: function(index) {
changes_applied.splice(index, 1);
}
}
});
When a change is detected the change is pushed onto the changes_applied
array, and it shows up in the "Changes Applied" div as expected. The deletes also work, which just calls the remove
method on the vue object.
I also have a "clear" button that's not connected to the vue instance, and when it's clicked it sets the data source back to an empty array using changes_applied = [];
The problem is that after this is cleared using the button, the changes / additions to the changes array no longer show up in the vue element-- it's like the vue element is no longer attached to the changes_applied
array.
Am I missing a binding or something here that needs to happen, or is there a "vue way" to clear the vue data without touching the actual source array?
Upvotes: 1
Views: 2527
Reputation: 4782
Mark_M already provided a good explanation, I'll add a demo, since I think its easier to understand how it works.
You can copy the value of the array to data, but then all operations must be done to the data directly:
const changes_applied = [
{id: 1},
{id: 2},
{id: 3}
];
const vm = new Vue({
el: '#app',
data: {items: changes_applied},
methods: {
add() {
const id = this.items.length + 1
this.items.push({id})
},
remove() {
this.items.pop()
},
clear() {
this.items = []
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<div>
<button type="button" @click="add">Add</button>
<button type="button" @click="remove">Remove</button>
<button type="button" @click="clear">Clear</button>
</div>
<ul name="list">
<li v-for="item in items" :key="item.id">
Item {{ item.id }}
</li>
</ul>
</div>
Upvotes: 1
Reputation: 3918
Your items array is initialized with changes_applied but does not mantaing bindings, it's just the default value for items when the instance is created. So if you change the changes_applied this will not affect the items array on vue instance.
example
new Vue({
el: '#app',
data: function () {
return {
items: myArr,
newItem: ''
}
},
methods: {
addItem () {
this.items.push(this.newItem)
this.newItem = ''
},
remove (index) {
this.items.splice(index, 1)
},
clear () {
this.items = []
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<input type="text" v-model="newItem" />
<button @click="addItem">Add</button>
<button @click="clear">Clear</button>
<p v-for="(item, index) in items" @click="remove(index)">{{item}}</p>
</div>
<!-- from outside vue instance-->
<button onClick="clearFromOutside()">clear from outside</button>
<script>
var myArr = ['hola', 'mundo'];
function clearFromOutside() {
console.log(myArr)
myArr = [];
console.log(myArr)
}
</script>
Upvotes: 2
Reputation: 92440
You shouldn't be changing the changes_applied
array; Vue isn't really reacting to changes on that array. It only sort of works when this.items
is pointed to the same array reference. When you change that reference by reassigning changes_applied
it breaks because you are then manipulating changes_applied
but it is not longer the same array as this.items
.
You should instead be manipulating this.items
directly:
methods: {
remove: function(index) {
this.items.splice(index, 1);
}
To clear it you can set:
this.items = []
and it will work as expected.
Upvotes: 2