Search code examples
javascriptarraysvuejs2splicearray-splice

Vue array.splice removing wrong item from list


I have a list and I am using a for loop to loop through it. The structure looks like this:

salesLists: { 
  1: [ [], [], [] ]
  2: [ [], [] ]
}

And html:

<div v-for="(saleLists, index) in salesLists">
    <my-comp v-for="(item, i) in saleLists" :key="i" :index="parseInt(i)+1"></my-comp>
</div>

Now, I am trying to remove items from salesLists[1] array. I have a button for that and @click="removeForm":

removeForm(e) {
        var index = parseInt(e.target.getAttribute('data-index')) - 1 // = 2
        var client = e.target.getAttribute('data-client')             // = 1
        //Vue.delete(this.salesLists[client], index);
        this.salesLists[client].splice(index, 1)
        this.$forceUpdate()
}

It removes it, however, as I didn't specify any keys and it's just empty arrays (i assume), it is not removing the right element from the DOM. It removes index of 2, but as it is v-for looping through the item, and count reduces, it only removes the last item in the end.

What is the proper way of overcome this issue? :/

Here is a Fiddle: https://jsfiddle.net/8rvfz40n/ try writing different values for each input field and removing the middle one, you'll see it will remove the last one


Solution

  • <div v-for="(saleLists, index) in salesLists">
        <my-comp v-for="(item, i) in saleLists" :key="i" :index="parseInt(i)+1"></my-comp>
    </div>
    

    The use of the index as key is the problem, when you delete a item from the middle the index that is lost is the last.

    In my case the solution that I found is add a unique "Hash" to the items, like an ID, but if the items are news, the ID is null.

    The hash that I use is a timestamp:

    Hash: new Date().getTime()
    

    And then:

     <div v-for="(saleLists, index) in salesLists">
         <my-comp v-for="(item, i) in saleLists" :key="item.Hash" :index="parseInt(i)+1"></my-comp>
     </div>