I'm trying to make a multiple text input component. There's a parent Vue component to manage individual fields and a component for a single input.
The parent component renders the child components via a v-for which is bound to an array of objects.
data() {
return {
lastItemId: 0,
items: [{ id: this.lastItemId, value: '', showDeleteBtn: false}]
}
},
Template:
<div>
<input-item v-for='(item, index) in items'
:key="item.id"
:default-data="item"
@itemAdded="addItemAfter(index)"></input-item>
</div>
Whenever the user starts typing in the last field in the list I'm emitting an event to add a new text field after it.
addItemAfter(index) {
if (index == this.items.length - 1) {
this.items.push({
id: ++this.lastItemId,
value: '',
showDeleteBtn: false
});
}
}
This works just fine. However, I also need to update the item at the current index to display the delete button near that field. Whatever I do, Vue doesn't re-render that component, unless I set an object with a different ID to that index - which is not what I want.
Things I have tried:
this.items[index].showDeleteBtn = true;
let item = this.items[index];
item.showDeleteBtn = true;
this.$set(this.items, index, item);
let item = this.items[index];
item.showDeleteBtn = true;
this.items.splice(index, 1, item);
this.$set(this.items[index], 'showDeleteBtn', true);
Update
This is the most important in this problem part of the child component:
<button class="btn text-danger" v-show="showDeleteBtn" @click.prevent="removeItem">
<i class="glyphicon glyphicon-remove"></i>
</button>
// ....................................
props: ['defaultData'],
data() {
return {
itemId: this.defaultData.id,
item: this.defaultData.value,
showDeleteBtn: this.defaultData.showDeleteBtn
}
},