I have a VueJS project. I have a v-for loop that has input fields in each row. I want to duplicate the row. But for some reason the duplicated fields are binding to the original row.
<div v-for="(e, index) in exercises" :key="index">
<div @click="duplicateRow(index, e)" >
<input type="text" v-model="e.weight" />
<input type="text" v-model="e.height" />
</div>
</div>
duplicateRow(index, e){
this.exercises.splice(index, 0, e);
}
So it duplicates perfectly, but when I change the values of the new row it also changes the values of the original row. This happens no matter how many rows I add.
I feel like the answer is going to be about reactivity but I'm feeling stupid and lost.
CodePudding user response:
Using splice to approach duplicating items is not effective in my opinion, because the item you pointed to has the reactivity, and you're deep cloning it and append it to your array. The best way to do it just using push (if you don't mean latest item must contain the item you already stored)
So you just need to do this at your duplicateRow
method
duplicateRow(index, e){
this.exercises.push({})
}
example can be tested here: https://jsfiddle.net/7bpu6wen/8/
CodePudding user response:
The problem is that a new row is actually a reference to the exact same object as the original row. To create a new object, you have to clone the original one.
There are a couple of ways to do that. If the object doesn't have nested properties, you can do a shallow copy with Object.assign()
or spread operator. If it does, you can use JSON.parse(JSON.stringify())
or lodash cloneDeep()
(which is way faster) to make a deep copy.
Using shallow copy:
duplicateRow(index, e){
this.exercises.splice(index, 0, {...e});
}
Using deep copy:
duplicateRow(index, e){
this.exercises.splice(index, 0, JSON.parse(JSON.stringify(e)));
}