3

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?

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

2 Comments

You could make things easier for yourself by doing something like [ { value: 'A' }, { value: 'B' } ]. Also, make sure to set the :key properly in your v-for if you're using it. Writing this helps me understand a lot: jsfiddle.net/crswll/ewhewzkz/21
Thanks, @BillCriswell ! Actually the objects I'm using are way more complex than the example I come up with (it has a lot of properties with sub-arrays, object, etc...) The other thing is: :key-ing are not only important when using v-for with <transition>? Or at least that's what I read somewhere, and that is what the console error messages were complaining about.
0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.