I'm getting the above error, when trying to edit a property value of an object inside list. Please refer below code for better understanding.
HTML:
<template>
<div class="container">
<div class="slds-grid slds-gutters">
<div class="slds-col" for:each={lstQuotes} for:item="objQuote" for:index="pindex" key={objQuote.Id}>
Quote : <span>{objQuote.sQuoteName}</span><br/>
Opportunity : <span>{objQuote.sOpptName}</span><br/>
<div>
<template for:each={objQuote.lstComments} for:item="objComment" for:index="index">
<div key={objComment.sRecordId}>
<span if:true={objComment.bEditing}>
<input type="text" value={objComment.sComment}/>
</span>
<span class="comment" if:false={bEditing}>{objComment.sComment}</span>
<span class="createdDate">{objComment.sCreatedDate}</span>
<span class="createdBy">{objComment.sCreatedBy}</span>
<span if:true={objComment.bShowEdit}>
<a onclick={handleEdit} data-pindex={pindex} data-index={index}>Edit</a>
</span>
</div>
</template>
</div>
<div>
<input type="button" name={objQuote.sQuoteId} value="Add Comment" onclick={showCommentBox} />
<input class="hide" data-id={objQuote.sQuoteId} data-index={index} value={objQuote.sComment} onkeyup={changeComment}/>
<input type="button" class="hide" data-index={index} data-id={objQuote.sQuoteId} value="Save" onclick={saveComment} />
</div>
</div>
</div>
</div>
</template>
The error is thrown when I click on Edit anchor tag, resulting in handleEdit js method being called. If you look at the html, you'll understand that I am displaying the comment for respective quote dynamically inside a span using {objComment.sComment} and on click of edit, I'll be displaying the same comment value inside an input field to allow edits to the comment. I use a boolean variable bEditing to hide and show input/span comment.
Below is the JS for better understanding:
@track lstQuotes =[];
@track lstQuotesTemp = [];
@track lstComments = [];
//sComment = '';
@wire(QUOTE_DATA)
quotesData({error, data}){
if(data){
console.log('data : ' ,data);
this.lstQuotes = data;
//Create copy of records
this.lstQuotesTemp = this.lstQuotes.map( obj => ({
...obj
}));
}
else if(error){
console.log('error : ',error);
}
}
The above wire method gets data from back-end which is displayed inside the web component.
Now lstQuotesTemp holds a list of records, and under each record there is a list of comments, lstComments.
I created lstQuotesTemp simply because lstQuotes is read only and changes to it's records would result in error.
Now, let's see what handleEdit method does:
handleEdit(event){
let parentIndex = event.target.dataset.pindex;
let index = event.target.dataset.index;
console.log('Comment Record : ' ,this.lstQuotesTemp[parentIndex].lstComments[index].bEditing);
this.lstQuotesTemp[parentIndex].lstComments[index].bEditing = true;
}
It simply finds the comment record using index to make it editable on click of Edit. However, it seems that the lstComments is still read only even after creation of a copy of it's parent list.
Can someone please suggest a way to fix this error?
I believe creating a copy of lstComments( which is a list on record level of lstQuotes) while creating a copy of lstQuotes -> lstQuotesTemp should resolve this issue. However, I'm not sure how I can achieve this?
To create a copy of lstQuotes I used below:
this.lstQuotesTemp = this.lstQuotes.map( obj => ({
...obj
}));
Best Answer
I was able to solve the above. The issue was that lstComments under lstQuotesTemp was read-only and thus had to create their copy. Below is what I did :
It worked as expected after creating a copy of lstQuotesTemp.lstComment.