0

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

2 Answers 2

3

@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!

1

This type of error(Cannot assign to read-only property) generally occurs on update of public property @api decorator variable value.

As I see from your code you are trying to update pfList property, Check if this public property(@api), If So change into @track or clone the pfList into a new variable.

EDIT

let tempPickList  = 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 
3
  • pfList is already a @track property. I tried the clone option too, the error doesn't pop up, but I'm not getting the expected result. I have updated my post - please see my description below "Analysis of clone option". Commented Mar 24, 2020 at 17:50
  • @DhivyaUday I do see pfList is List of JSON, you have to loop through the JSON to match the key and update the JSON. I edit my answer
    – Sarvesh
    Commented Mar 25, 2020 at 6:09
  • pfList is actually list of child records of Opportunity that I am fetching from Salesforce through a controller, and I am iterating through that list to display the records in the related list. I used JSON.stringify just to display the data in the developer console. Anyway, I tried your logic, and it doesn't let me update tempPickList either. I have updated my post by adding the controller code and the initial logic in javascript to load the related list contents. Commented Mar 25, 2020 at 13:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .