How to add and remove item from array in components in Vue 2

157,100

Solution 1

There are few mistakes you are doing:

  1. You need to add proper object in the array in addRow method
  2. You can use splice method to remove an element from an array at particular index.
  3. You need to pass the current row as prop to my-item component, where this can be modified.

You can see working code here.

addRow(){
   this.rows.push({description: '', unitprice: '' , code: ''}); // what to push unto the rows array?
},
removeRow(index){
   this. itemList.splice(index, 1)
}

Solution 2

You can use Array.push() for appending elements to an array.

For deleting, it is best to use this.$delete(array, index) for reactive objects.

Vue.delete( target, key ): Delete a property on an object. If the object is reactive, ensure the deletion triggers view updates. This is primarily used to get around the limitation that Vue cannot detect property deletions, but you should rarely need to use it.

https://vuejs.org/v2/api/#Vue-delete

Share:
157,100

Related videos on Youtube

Jeffrey
Author by

Jeffrey

Building Contractor from Trinidad who has always been interested in programming but never had the chance until now.

Updated on July 16, 2022

Comments

  • Jeffrey
    Jeffrey almost 2 years

    I made a component "my-item" which contains three elements: a dropdown (populated by "itemList") and two input boxes populated from the dropdown. This component is considered a row.

    I am trying to add and delete one row at a time but two things i am not sure about. (1) what to add to the rows array? (2) why is this.rows.splice(index,1) removing only the last row?

    https://jsbin.com/mugunum/edit?html,output

    Thanks

    <div id="app">
        <my-item v-for="(row, index) in rows"
             :itemdata="itemList"
              v-on:remove="removeRow(index)">
        </my-item>
    <div>
        <button @click="addRow"> Add Row </button>
    </div>
    </div>
    
    <template id="item-template">
    <div>
        <select v-model="selected">
            <option v-for="item in itemdata"  :value="item">
               {{ item.code }}
            </option>
        </select>
        <input type="text" placeholder="Text" v-model="selected.description">
        <input type="text" placeholder="value" v-model="selected.unitprice">
        <button v-on:click= "remove"> X </button>
    </div>
    </template>
    
    Vue.component('my-item', {
    props: ['itemdata'],
    template: '#item-template',
    data: function () {
        return {
        selected: this.itemdata[0]
        }
    },
    methods: {
        remove() {
            this.$emit('remove');
        }
    }
    }),
    
    new Vue({
    el: "#app",
    data: {
        rows: [],
        itemList: [
            { code: 'Select an Item', description: '', unitprice: ''},
            { code: 'One', description: 'Item A', unitprice: '10'},
            { code: 'Two', description: 'Item B', unitprice: '22'},
            { code: 'Three', description: 'Item C', unitprice: '56'}
        ]
    },
    
    methods: {
        addRow(){
           this.rows.push(''); // what to push unto the rows array?
        },
        removeRow(index){
           this.rows.splice(index,1); // why is this removing only the last row?
        }
    }
    })
    
  • Saurabh
    Saurabh over 7 years
    @Pyol7 You are not pushing anything in the rows, you have to first fix adding rows properly, than you will know the difference on which index you are removing.
  • Jeffrey
    Jeffrey over 7 years
    That is the problem. I don't know how to fix addRow
  • Jeffrey
    Jeffrey over 7 years
    Do I have to push the row component unto the rows array? and if so how?
  • Saurabh
    Saurabh over 7 years
    @Pyol7 check this and edited answer.
  • Jeffrey
    Jeffrey over 7 years
    Thanks, Its working but there is a lot of duplication. There must be a better way. I cleaned it up a bit but still not satisfied.
  • Saurabh
    Saurabh over 7 years
    @Pyol7 this seems good, I will suggest to use codereview.stackexchange.com for this purpose, post a link here, after asking there.
  • Damien Bezborodow
    Damien Bezborodow over 5 years