25

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
  • 71,488
  • 40
  • 181
  • 244
Jeffrey
  • 1,998
  • 1
  • 25
  • 22

2 Answers2

37

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)
}
tony19
  • 125,647
  • 18
  • 229
  • 307
Saurabh
  • 71,488
  • 40
  • 181
  • 244
  • @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. – Saurabh Dec 29 '16 at 15:23
  • That is the problem. I don't know how to fix addRow – Jeffrey Dec 29 '16 at 15:28
  • Do I have to push the row component unto the rows array? and if so how? – Jeffrey Dec 29 '16 at 15:33
  • @Pyol7 check [this](https://jsbin.com/bomavadune/1/edit?html,console,output) and edited answer. – Saurabh Dec 29 '16 at 15:53
  • 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. – Jeffrey Dec 29 '16 at 20:02
  • @Pyol7 this seems good, I will suggest to use codereview.stackexchange.com for this purpose, post a link here, after asking there. – Saurabh Dec 31 '16 at 04:53
8

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://v2.vuejs.org/v2/api/#Vue-delete

tony19
  • 125,647
  • 18
  • 229
  • 307
Damien
  • 1,140
  • 15
  • 22
  • Possible duplicate https://stackoverflow.com/questions/43046332/how-to-remove-an-item-from-an-array-in-vue-js – Damien Nov 15 '18 at 04:27