[SalesForce] [Cannot assign to read only property ‘‘ of object ‘#‘]

I am building an editable related list using LWC. I need to render percent, picklist, text and lookup fields in the related list. I am stuck on the picklist child component – unable to save the newly selected picklist value.

Component screenshots:

LWC table component for editable related list
LWC table component for editable related list - picklist dropdown

Code snippets:

HTML code-snippet where I include the picklist child component:

                   <template for:each={pfList} for:item="item" for:index="indexVar">
                        <tr key={item.Id} class="slds-hint-parent" ondblclick={onDoubleClickEdit}>
                            <td class="slds-size_1-of-11" data-label="Prospecting">
                                <div title="Prospecting">
                                    <template if:false={isEdited}>
                                        {item.Registration_Type__c}
                                    </template>
                                    <template if:true={isEdited}>
                                        <c-picklist 
                                            unique-key={item.Id} 
                                            object-api-name="Portfolio__c" 
                                            record-type-id={item.RecordTypeId} 
                                            selected-value={item.Registration_Type__c}  
                                            pick-listfield-api-name="Registration_Type__c" 
                                            variant="label-hidden"
                                            onpicklistchange={handlePicklistChange}>
                                        </c-picklist>
                                    </template>
                                </div>
                            </td>
                         </tr>
                    </template>

Javascript code-snippet (parent component code):

import fetchPortfoliosFromOpps from '@salesforce/apex/OppPortfoliosController.getPortfoliosForOpp';

@track pfList = [];

_wiredResult;
    @wire(fetchPortfoliosFromOpps, { recordId: "$recordId" })
    wiredCallback(result) {
        console.log('****entered wiredCallback');
        this._wiredResult = result;
        if (result.data) {
            this.pfList = result.data;
            this.error = undefined;

            for(var key in result.data){
                console.log('***key: '+key);
                console.log('***result.data[key]: '+result.data[key]);
                this.pfMap.push({value: result.data[key], key: key});
                console.log('***this.pfMap: '+this.pfMap);
            }
        } 
        else if (result.error) {
            this.error = result.error;
            this.pfList = undefined;
        }console.log('****JSON.stringify(this.pfList): '+JSON.stringify(this.pfList));
    }

    handlePicklistChange(event){
        
        let eventData = event.detail;
        let pickValue = event.detail.selectedValue;
        let uniqueKey = event.detail.key;
        // 1. console.log('pickValue: '+pickValue);
        // 2. console.log('uniqueKey: '+uniqueKey);

        let element = this.pfList.find(ele => ele.Id === uniqueKey);
        // 3. console.log('before element.Registration_Type__c: '+element.Registration_Type__c);
        // 4. console.log('element extensible?: '+Object.isExtensible(element));

        // 5. Object.assign(element.Registration_Type__c, pickValue);
        // 6. this.pfList.Registration_Type__c = {...pickValue};

        element.Registration_Type__c = pickValue;
        console.log('after element.Registration_Type__c: '+element.Registration_Type__c);
        this.pfList = [...this.pfList];
    }

Controller Code:

@AuraEnabled(cacheable = true)
    public static List<Portfolio__c> getPortfoliosForOpp(String recordId){
        System.debug('****Entered getPortfoliosForOpp() recordId: '+recordId);
        
        return [SELECT Id, RecordTypeId, Equity_Target__c, Bond_Target__c, Registration_Type__c, Fee_Type__c, Fee_Schedule__c, 
                Discretionary__c, Billing_In__c, Proxy_Voting_by_Us__c, Revenue_Source__c, Custodian__c, Custodian__r.Id, 
                Custodian__r.Name, Custodian__r.CustodianUrl__c, ManagedNew__c, PortfolioUrl__c 
                FROM Portfolio__c WHERE Opportunity__c =: recordId];
    }

I am able to select a new value from the picklist dropdown, but I'm unable to save it back to the Registration_Type__c field on the object using the code:

element.Registration_Type__c = pickValue

I get the error: [Cannot assign to read only property 'Registration_Type__c' of object '#']

I looked up for ways to overcome this error, but couldn't figure anything yet. I tried #5 and #6 (commented statements in the above JS code) which gave a similar error.

Console statements output:
1: displays the new picklist value that I select
2: give the id of the row I edit on the table
3: Old picklist value (the value that existed before my new selection)
4: false

Any ideas on how this can be fixed, and the reason why the property is in read-only mode?


Analysis of clone option:

I tried to clone the list, but I am unable to get pfList updated, which I would require in the save button function.

handlePicklistChange(event){
        
        let eventData = event.detail;
        let pickValue = event.detail.selectedValue;
        let uniqueKey = event.detail.key;
        console.log('pickValue: '+pickValue);
        console.log('uniqueKey: '+uniqueKey);
        
        let element = Object.assign({}, this.pfList);
        console.log('before this.pfList = [...this.pfList]: '+this.pfList.find(ele => ele.Id === uniqueKey).Registration_Type__c);

        element.Registration_Type__c = pickValue;

        console.log('after element.Registration_Type__c: '+element.Registration_Type__c);
        this.pfList = [...this.pfList];
        console.log('after this.pfList = [...this.pfList]: '+this.pfList.find(ele => ele.Id === uniqueKey).Registration_Type__c);
        console.table(JSON.stringify(this.pfList));
    }

console.log output

Best Answer

@Sarvesh : I dug a little deeper into your solution and replaced

let tempPickList = this.pfList

with

let tempPickList = JSON.parse(JSON.stringify(this.pfList));

I am able to update pfList now! Yeayy!

Updated code-snippet:

let tempPickList  = JSON.parse(JSON.stringify(this.pfList));

tempPickList.map(e =>{
    if(e.Id === uniqueKey){
         e.Registration_Type__c = pickValue;
    }
})

//Check if the value is updated.
console.log(tempPickList)
this.pfList = tempPickList

Thank you for your idea!