Search code examples
vue.jsvuejs2vue-componentvuex

Removing specific object from array keeps removing last item


Here is what I have and I will explain it as much as I can:

  1. I have a modal inside my HTML code as shown below:

     <div id="favorites-modal-edit" class="modal">
         <div class="modal-background"></div>
         <div class="modal-card px-4">
             <header class="modal-card-head">
                 <p class="modal-card-title">Favorites</p>
                 <button class="delete" aria-label="close"></button>
             </header>
             <section class="modal-card-body">
                 <div class="container">
                     <div id="favorites-modal-edit-wrapper" class="columns is-multiline buttons">
                         <favorites-edit-component v-for="(favorite, index) in favorites_list" :key="favorite.id" :favorite="favorite" />
                     </div>
                 </div>
             </section>
             <footer class="modal-card-foot">
                 <button class="button" @click="addItem">
                     Add Item
                 </button>
             </footer>
         </div>
     </div>
    

The id="favorites-modal-edit" is the Vue.js app, then I have the <favorites-edit-component /> vue.js component.


Here is the JS code that I have:

I have my favorites_list generated which is an array of objects as shown below: enter image description here

const favorites_list = [
    {
        id: 1,
        name: 'Horse',
        url: 'www.example.com',
    },
    {
        id: 2,
        name: 'Sheep',
        url: 'www.example2.com',
    },
    {
        id: 3,
        name: 'Octopus',
        url: 'www.example2.com',
    },
    {
        id: 4,
        name: 'Deer',
        url: 'www.example2.com',
    },
    {
        id: 5,
        name: 'Hamster',
        url: 'www.example2.com',
    },
];

Then, I have my vue.js component, which is the favorites-edit-component that takes in the @click="removeItem(this.index) which is coming back as undefined on the index.

Vue.component('favorites-edit-component', {
   template: `
    <div class="column is-half">
      <button class="button is-fullwidth is-danger is-outlined mb-0">
        <span>{{ favorite.name }}</span>
        <span class="icon is-small favorite-delete" @click="removeItem(this.index)">
          <i class="fas fa-times"></i>
        </span>
      </button>
    </div>
   `,
    props: {
        favorite: Object
    },
    methods: {
       removeItem: function(index) {
           this.$parent.removeItem(index);
       },
    }
});

Then I have the vue.js app that is the parent as shown below:

new Vue({
    el: '#favorites-modal-edit',

    // Return the data in a function instead of a single object
    data: function() {
        return {
            favorites_list
        };
    },
    methods: {
        addItem: function() {
            console.log('Added item');
        },
        removeItem: function(index) {
            console.log(index);
            console.log(this.favorites_list);
            this.favorites_list.splice(this.favorites_list.indexOf(index), 1);
        },
    },
});

The problem:

For some reason, each time I go to delete a item from the list, it's deleting the last item in the list and I don't know why it's doing it, check out what is happening:

enter image description here

This is the guide that I am following:
How to remove an item from an array in Vue.js

The item keeps coming back as undefined each time the remoteItem() function is triggered as shown below:
enter image description here

All help is appreciated!


Solution

    1. There is an error in your favorites-edit-component template, actually in vue template, when you want to use prop, data, computed, mehods,..., dont't use this => there is an error here: @click="removeItem(this.index)" => in addition, where is index declared ? data ? prop ?

    2. you're calling this.$parent.removeItem(index); then in removeItem you're doing this.favorites_list.splice(this.favorites_list.indexOf(index), 1); this means that you want to remove the value equal to index in you array no the value positioned at the index => this.favorites_list[index] != this.favorites_list[this.favorites_list.indexOf(index)]

    In addition, I would suggest you to modify the favorites-edit-component component to use event so it can be more reusable:

    favorites-edit-component:

    <template>
      <div class="column is-half">
        <button class="button is-fullwidth is-danger is-outlined mb-0">
          <span>{{ favorite.name }}</span>
          <span class="icon is-small favorite-delete" @click="$emit('removeItem', favorite.id)">
            <i class="fas fa-times"></i>
          </span>
        </button>
      </div>
    </template>
    

    and in the parent component:

    <template>
      ...
      <div id="favorites-modal-edit-wrapper" class="columns is-multiline buttons">
        <favorites-edit-component
          v-for="favorite in favorites_list"
          :key="favorite.id"
          :favorite="favorite"
          @removeItem="removeItem($event)"
        />
      </div>
      ...
    </template>
    
    <script>
    export default {
      data: function () {
        return {
          favorites_list: [],
        };
      },
      methods: {
        ...
        removeItem(id) {
          this.favorites_list = this.favorites_list.filter((favorite) => favorite.id !== id);
        }
        ...
      },
    };