Problem Statement:
I am trying to work on a design that involves replicating the Parties Being Served form fields on each Add button click. On clicking the Add Button, the corresponding PartyInfo object gets added to the PartyInfoList array

In the BaseButtonList.vue file, I use the PartyInfoList array to setup the v-for loop
<base-card
v-for="(data, index) of partiesInfoList" :key="index"
ref="childComponent"
@add-parties="updatePartiesInfoList"
@delete-party="deleteParty(index)"
:lastElement="index === partiesInfoListLength - 1"
>
However, it is important to note that initially the array has no elements. But, since I have no other way to enter the data to the array, I'm forced to load the form despite the partiesInfoList array having zero elements. I achieve this by setting the partiesInfoList with dummy data. This allows the initial form to be displayed. And when the Add Another button gets hit, this first real entry will be pushed to the 2nd index of the partiesInfoList.
However, this causes serious issues when deleting the entries from the array. The splice does function properly when I console log the output. But, Vue ends up deleting the wrong element from the DOM.
I have used a unique index key and also tried other possible keys, but all yield the same pernicious bug. Any help would be greatly appreciated. I think this is a really tricky design pattern, I can think of easier alternatives, but I want to get this working as a challenge. Maybe there's a better data flow I can set up or something.
Attached is the code
BaseCard.vue
<template>
//contains the template for the input form element
</template>
<script>
import { random } from '@amcharts/amcharts4/.internal/core/utils/String';
import { EventBus } from './bus.js';
export default {
emits:['add-parties','delete-party'],
props:['lastElement'],
data() {
return {
partyInfo:
{
id: '',
fullName: '',
preAuthorize: '',
serviceAddress: '',
},
validation: {
fullNameIsValid: true,
serviceAddressIsValid: true
},
hideAddButton: false,
formIsValid: true,
addServiceButtonText: '+ Add Service Notes (Optional)',
serviceNotes: [],
showServiceNotes: false,
showDeleteButton: true,
enteredServiceNote: '', //service notes addendum
}
},
computed : {
showServiceNotex(){
if(!this.showServiceNotes){
return '+Add Service Notes (Optional)'
}else{
return '- Remove Service Notes';
}
}
},
methods: {
setServiceNotes(){
this.showServiceNotes = !this.showServiceNotes;
},
addAnotherParty(){
this.validateForm();
if(this.counter === 0){
this.counter++;
this.lastElement = false;
}
if(!this.formIsValid){
return;
}
let emitObj = JSON.parse(JSON.stringify(this.partyInfo));
this.$emit('add-parties', emitObj); //event
},
deleteParty(){
this.$emit('delete-party');
},
validateForm(){
this.formIsValid = true;
if(this.partyInfo.fullName === ''){
this.validation.fullNameIsValid = false;
this.formIsValid = false;
}
if(this.partyInfo.serviceAddress === ''){
this.validation.serviceAddressIsValid = false;
this.formIsValid = false;
}
},
clearValidity(input){
this.validation[input] = true;
},
clearForm(){
this.partyInfo.fullName = '';
this.partyInfo.serviceAddress = '';
this.partyInfo.preAuthorize = false;
}
},
created(){
console.log('created');
}
}
</script>
Attached is the <BaseCardList> which renders the form elements in a v-for loop
BaseCardList.vue
<template>
<ul>
<base-card
v-for="(data, index) of partiesInfoList" :key="index"
ref="childComponent"
@add-parties="updatePartiesInfoList"
@delete-party="deleteParty(index)"
:lastElement="index === partiesInfoListLength - 1"
>
<!-- Wrapper for the `Parties Being Served` component-->
<template v-slot:title>
<slot></slot>
</template>
</base-card>
</ul>
</template>
<script>
import BaseCard from './BaseCard.vue';
export default {
components: { BaseCard },
data() {
return {
selectedComponent: 'base-card',
partiesInfoList : [
{id: 0,
fullName: 'dummy',
serviceAddress: 'dummy',
preAuthorize: ''
}
],
clearForm: false,
counter: 1
}
},
computed : {
hasParty(){
return this.partiesInfoList.length > 0;
},
partiesInfoListLength(){
return this.partiesInfoList.length;
}
},
methods: {
updatePartiesInfoList(additionalInfo){
// if(this.counter == 0){
// this.partiesInfoList.splice(0,1);
// }
this.partiesInfoList.push(additionalInfo);
this.counter++;
console.log(this.partiesInfoList);
console.log('The length of list is '+this.partiesInfoList.length);
},
deleteParty(resId){
// const resIndex = this.partiesInfoList.findIndex(
// res => res.id === resId
// );
// this.partiesInfoList.splice(resIndex, 1);
if(this.counter == 1){
return;
}
this.partiesInfoList.splice(resId, 1);
console.log('Index is '+resId);
console.log('after del');
console.log(this.partiesInfoList);
}
}
}
</script>
Actual Output Bug on screen : The adjacent element gets removed from the DOM. Say,I click on delete for the 'Second' but 'Third' gets removed. But, if there's an empty form element at the end of the v-for, then this one gets deleted.

