marchello
marchello

Reputation: 2136

Vuejs 2 moving items in array, doesn't retain array indexing

I have an array of elements that I supply for a vue component as a reactive data source (I'm inspecting the data with the vue chrome extension):

the view: [A,B,C,D,E]
the data: [A,B,C,D,E]

I want to move an item (D) to a new position (before B), so first I remove the element with splice, then reinsert it at the desired index:

the view: [A,D,B,C,E]   
the data: [A,B,C,D,E]

So when I hover over in the Chrome Vue inspector over the second component, in the view the third column gets highlighted. If I hover over the 3rd element in the data, in the view the 4th element get highlighted, and so on.

The view updates correctly, but I want underlying the data to follow it. In the array the elements are objects.

I guess this is because they are passed as reference?

Upvotes: 3

Views: 2150

Answers (2)

marchello
marchello

Reputation: 2136

I think I've found it, instead of splice I should use set and remove on the vue instance: https://v2.vuejs.org/v2/api/#Vue-set

You should avoid directly setting elements of a data-bound Array with indices, because those changes will not be picked up by Vue.js. Instead, use the augmented $set() method

Upvotes: 1

Vincent Tang
Vincent Tang

Reputation: 4170

I had the same issue as well, what happened was I didn't use unique key values for each vue object in the array. I used the index in the array as the key. So when items were resorted, some of the data would be binded to different items because keys were swapped.

What I used was a Date.now() function to initialize a UUID to set for each key


So for instance, say we had the key set to the index of the array

[ 0, 1, 2, 3, 4] - The keys
[A0,B0,C0,D0,E0] - The array of objects
[A1,B1,C1,D1,E1] - The data attribute inside each of the objects in array

So [A0] has a key of [0], and data attribute of [A1]. Say we swap [A0] and [B0]

[ 0, 1, 2, 3, 4] - the key
[B0,A0,C0,D0,E0] - the array of objects
[A1,B1,C1,D1,E1] - the data attribute assigned to each object in array

Now [A0] is binded to the data attribute of [B1], because [B1] is binded to the key of [1] and A[0] key is [1]

This is never what you want, so you want to make each key unique instead. A common way of doing this is using a Date.now() method upon data initialization, or a create a UUID


In Summary

Example in Vue for creating a unique UUID for each object when using vue methods

    methods: {
      _addGroup: function() {
        let result = {
          sortId: this.wizardGroups.length + 1,
          text: 'Hello world'
          uuid: Date.now(),
        };
        this.wizardGroups.push(result);
      }

Assign that value to the key during v-for iteration

<child-component
  v-for="wizardGroup in wizardGroups"
  :key="wizardGroup.uuid">
</child-component>

Upvotes: 0

Related Questions