0

My objective is to build a LWC component which will display the list of related opportunity records based on account and also enable users to update the stage and amount fields. I am getting the child records displayed correctly, but am encountering a few errors:

  1. whenever I type anything in the fields, I get a popup message- This page has an error. You might just need to refresh it. First, would you give us some details? (We're reporting this as error ID: 736493086)
  2. The update operation is not occuring for some reason.
  3. I also need help in the stage picklist field, it is currently getting displayed in the form of text, but I need the picklist values to appear.

Thanks

HTML:

<template>
    <lightning-card>

        <template for:each={opportunities} for:item="opp">
            <tr key={opp.Id}>
                <td><lightning-input label="Opp Name" type="text" value={opp.Name} onchange={handleInputChange} data-field="Name" ></lightning-input></td>
                <td><lightning-input label="Opp Stage Name" type="text" value={opp.StageName} onchange={handleInputChange} data-field="StageName" ></lightning-input></td>
                <td><lightning-input label="Opp Amount" type="number" value={opp.Amount} onchange={handleInputChange} data-field="Amount" ></lightning-input></td>
                <td>
                    <lightning-button label="Save" onclick={handleSave} data-id={opp.Id}></lightning-button>
                    
                </td>
            </tr>
        </template>
      
    

    </lightning-card>
</template>

JS:

import { LightningElement,api, wire, track } from 'lwc';

import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import displayRelatedOpp_Account from '@salesforce/apex/relatedOpp_Account.displayRelatedOpp_Account';
import updateOppDetails_Test3 from '@salesforce/apex/relatedOpp_Account.updateOppDetails_Test3';
//import { refreshApex } from '@salesforce/apex';



import NAME_FIELD from '@salesforce/schema/Opportunity.Name';
import STAGENAME_FIELD from '@salesforce/schema/Opportunity.StageName';
import AMOUNT_FIELD from '@salesforce/schema/Opportunity.Amount';

export default class DisplayRelatedOpp_Test3 extends LightningElement {

    @api recordId;
    columns;
    draftValues = [];
    @api opportunities =[];

   

    @wire(displayRelatedOpp_Account, { accId: '$recordId' })
    opps(result)
    {
        
        if (result.error)
        {
            this.opportunities = undefined;
        }
        else if (result.data)
        {
            this.opportunities = result.data;
        }
    }

    handleInputChange(event)
    {
        if(event.target.label=='Opp Name')
        {
            opportunities.name=event.target.value;
        }
        else if (event.target.label=='Opp Stage Name')
        {
            opportunities.stagename=event.target.value;
        }
        else if (event.target.label=='Opp Amount')
        {
            opportunities.amount=event.target.value;
        }
    }

  

    handleSave(event)
    {
        updateOppDetails_Test3({accountId: this.recordId, oppName: this.opportunities.name, oppStage: this.opportunities.stagename, oppAmount: this.opportunities.amount})
        .then(oppDetail => {console.log(JSON.stringify(oppDetail))})
        .catch(error=>(console.log(error)))

        this.dispatchEvent(
            new ShowToastEvent({
                title: 'Success',
                message: 'Opportunity updated',
                variant: 'success'
            })
        );
    }

}

APex:

public with sharing class relatedOpp_Account {


    @AuraEnabled(cacheable=true)
    public static List<Opportunity> displayRelatedOpp_Account(string accId) {

        List<opportunity> oppList = [select id, name, stagename, amount, accountId from opportunity WHERE AccountId = :accId];

        if (!oppList.isEmpty())
        {
            return oppList;
        }
        return null;

    }


    @AuraEnabled

    public static String updateOppDetails_Test3(String accountId, string oppName, string oppStage, integer oppAmount )

    {
           // system.debug(OppData);
           // return 'done';

        list<opportunity> updatedOppList = new list<opportunity>();

        if(accountId!=null)
        {
            Opportunity opp = new opportunity();
            opp.accountId = accountId;
            opp.name = oppName;
            opp.stagename = oppStage;
            opp.amount = oppAmount;
            updatedOppList.add(opp);
        }
       

        if(!updatedOppList.isempty())
        {
            update updatedOppList;
        }
        return null;
    }
}

1 Answer 1

0
@api opportunities =[];

Makes the field read-only. Remove the @api.


this.opportunities = result.data;

Wire data is always read-only. Clone it first:

this.opportunities = result.data.map((record)=>({...record}));

@AuraEnabled(cacheable=true)
public static List<Opportunity> displayRelatedOpp_Account(string accId) {

    List<opportunity> oppList = [select id, name, stagename, amount, accountId from opportunity WHERE AccountId = :accId];

    if (!oppList.isEmpty())
    {
        return oppList;
    }
    return null;

}

Don't return null values, it just makes it more likely to crash your code.

@AuraEnabled(cacheable=true)
public static List<Opportunity> displayRelatedOpp_Account(string accId) {
    return [select id, name, stagename, amount, accountId from opportunity WHERE AccountId = :accId];
}

opportunities.name=event.target.value;

opportunities is an array. You need to find the right element in that array.

<lightning-input data-id={opp.Id} ...>

...

const opp = this.opportunities.find((record)=>record.Id === event.target.dataset.id);

You can use the name attribute in HTML to reduce your code complexity to just:

handleInputChange(event) {
  const opp = this.opportunities.find((opp)=>opp.id === event.target.dataset.id);
  opp[event.target.name] = event.target.value;
}

With your template having:

<lightning-input name="Name" ...
<lightning-input name="StageName" ...
<lightning-input name="Amount" ...

handleSave has the same problem; you're assuming it's not an Array.

First, change your Apex:

@AuraEnabled public static void updateOppDetails_Test3(Opportunity[] records) {
  update records;
}

Then, change your JavaScript to match:

handleSave(event) {
    updateOppDetails_Test3({ records: this.opportunities })
        .then(oppDetail => {
            console.log(JSON.stringify(oppDetail));
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'Opportunity updated',
                    variant: 'success'
                })
            );
        })
        .catch(error => (console.log(error)))
}

Notice how we put the toast message inside the then block. We don't want to display success before it actually saves successfully.


I also need help in the stage picklist field, it is currently getting displayed in the form of text, but I need the picklist values to appear.

Because you used lightning-input. If you want a picklist field, you need to use the appropriate type of element, such as lightning-select or lightning-combobox. You'll also need getPicklistValues to load the picklist values, and possibly getObjectInfo as well.


There's still some cleanup to do here, but this should be enough to fix the first round of problems in your code.

0

You must log in to answer this question.

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