This is simplified version of bigger component I'm working on. Please help me to solve the mystery - why I'm getting error on deleting (splicing) the last item from the list ?
- If you delete one by one - no error. It happens, only when the last item is deleted and at least one item is in front of it.
- If
@click="handleProductLineTap(line, index)"
is removed at v-for - no error.
<template>
<div v-for="(row, index) in this.rows" :key="index" v-bind:id="`row-${index}`" @click="handleProductrowTap(index)">
<div v-bind:id="`row-${index}`" v-bind:>
<span>{{ row.text }}</span> <button style="background-color: white; border:black;" @click.prevent="deleteRow(row, index)">Delete me </button>
</div>
</div>
</template>
<script>
export default {
name: 'TestRow',
created() {},
data() {
return {
rows: [
{'id':1, text: 'Granny smith', type: 'apple'},
{'id':2, text: 'Conference', type: 'pear'},
{'id':3, text: 'Alpine', type: 'strawberry'},
],
currentRowIndex: 0
}
},
methods: {
//returns css styling to every row in v-for.
//It sets color of the row according to the row.type and highlights selected row (if currentRowIndex == index).
rowCssDecorations(row) {
var resultingCss = ''
//change color according to rows.type
switch (row.type) {
case 'apple':
resultingCss = resultingCss 'appleClass'
break
case 'pear':
resultingCss = resultingCss 'pearClass'
break
case 'strawberry':
resultingCss = resultingCss 'strawberryClass'
break
default:
resultingCss = resultingCss 'defaultClass'
break
}
//Hliglight the current row
if (this.rows[this.currentRowIndex].id == row.id) {
resultingCss = resultingCss ' borderSelected '
} else {
resultingCss = resultingCss ' borderNormal '
}
return resultingCss
},
//deletes the row
deleteRow(index) {
this.rows.splice(index, 1)
},
//Simply sets the selected row id to currentRowIndex .
handleProductrowTap( index) {
this.currentRowIndex = index
},
},
}
</script>
<style lang="scss" scoped>
.appleClass {
background-color: greenyellow;
}
.pearClass {
background-color: palegoldenrod;
}
.strawberryClass {
background-color: red;
}
.defaultClass {
background-color: gainsboro;
}
.borderSelected{
border-color: black;
border-width: 4px;
}
.borderNormal{
border-color: black;
border-width: 2px;
}
</style>
CodePudding user response:
After looking into the fiddle link you shared, I came up with below observations/root cause :
You are calling
deleteRow
method with two parameters (row, index) but in the method definition you are accepting onlyindex
which causing the issue in delete the record.To resolve this you have to just pass the index in
deleteRow
method from the template.Another observation is that as you are passing
row
andindex
both inrowCssDecorations
method. Hence, no need ofcurrentRowIndex
, you can directly use theindex
inrowCssDecorations
method.
Live Demo :
new Vue({
el: '#app',
data: {
rows: [{
'id': 1,
text: 'Granny smith',
type: 'apple'
},
{
'id': 2,
text: 'Conference',
type: 'pear'
},
{
'id': 3,
text: 'Alpine',
type: 'strawberry'
}
],
currentRowIndex: 0
},
methods: {
deleteRow(index) {
this.rows.splice(index, 1)
},
rowCssDecorations(row, index) {
var resultingCss = ''
//change color according to rows.type
switch (row.type) {
case 'apple':
resultingCss = resultingCss 'appleClass'
break
case 'pear':
resultingCss = resultingCss 'pearClass'
break
case 'strawberry':
resultingCss = resultingCss 'strawberryClass'
break
default:
resultingCss = resultingCss 'defaultClass'
break
}
//Hliglight the current row
if (this.rows[index].id == row.id) {
resultingCss = resultingCss ' borderSelected '
} else {
resultingCss = resultingCss ' borderNormal '
}
return resultingCss
},
//deletes the row
deleteRow(index) {
this.rows.splice(index, 1)
}
}
})
.appleClass {
background-color: greenyellow;
}
.pearClass {
background-color: palegoldenrod;
}
.strawberryClass {
background-color: red;
}
.defaultClass {
background-color: gainsboro;
}
.borderSelected {
border-color: black;
border-width: 4px;
}
.borderNormal {
border-color: black;
border-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="(row, index) in this.rows" :key="index" v-bind:id="`row-${index}`">
<div v-bind:id="`row-${index}`" v-bind:>
<span>{{ row.text }}</span> <button @click.prevent="deleteRow(index)">Delete me</button>
</div>
</div>
</div>
CodePudding user response:
You should use @click.stop
instead of @click.prevent