1

I wish to query for parent record data (which is a lookup). How do I pass a parameter to the apex class that is not the '$recordId'?

Apex class:

public with sharing class cc_CaseOrderController {
    @AuraEnabled(cacheable=true)
    public static Order getOrder(String salesOrder) {
        return [SELECT Id FROM Order WHERE Id = :salesOrder];
    }
}

LWC:

import { LightningElement, wire, api } from 'lwc';
import getOrder from '@salesforce/apex/cc_CaseOrderController.getOrder';
import SALES_ORDER_FIELD from '@salesforce/schema/Case.Sales_Order__c';


export default class OrderCaseViz extends LightningElement {
    @api recordId;
    @wire (getOrder, {salesOrder: SALES_ORDER_FIELD}) cases; // this cant be done?
    
}

Whats the way forward to pass the SALES_ORDER_FIELD to my apex class and have the Order returned so I can render it on an AppPage?

5
  • SALES_ORDER_FIELD represents the field name and not the value. Why not just send the recordId (case record ID) to the apex method and let the apex method query to find the parent order and its details?
    – arut
    Sep 9, 2020 at 13:18
  • That means I would have to do two queries, no?
    – erikvm
    Sep 9, 2020 at 13:24
  • Yes, the first query to get the parent record ID and the second query is same as what you already have (all within the same apex method). Or, you could write it in a single query too (access parent record field values using the merge fields or dot notation).
    – arut
    Sep 9, 2020 at 13:26
  • That could work: @wire(caseData, {recordId: '$recordId'}) caseinfo; and in the query Sales_Order__r.Status__c. What would the template look like then? {caseinfo.Sales_Order__r.Status__c}?
    – erikvm
    Sep 9, 2020 at 13:32
  • No, don't do it this way. You might run into undefined errors as the wire service may trigger more than once. Use a wired function instead. I'll post a sample code in few min.
    – arut
    Sep 9, 2020 at 14:11

2 Answers 2

1

Summarizing my comments as an answer with sample code snippet.

SALES_ORDER_FIELD represents the field name (not the value) and hence, cannot be used this way. Pass the case record ID (recordId) to the apex method and let the apex method query for the parent record ID or the parent record field values.

In the LWC JS file, code for this wire service call should be something like this:

parentOrderStatus; // private field to store the case order status
error;

@wire(caseData, {recordId: '$recordId'})
caseinfo(error, data){
   if(data){
       this.parentOrderStatus = result.data.Sales_Order__r.Status__c;
   }
   else if(error){
       this.error = error;
   }
};

Bind parentOrderStatus directly in the template HTML (or you could also make use of a getter property). Note that the wire service may get triggered more than once during the component lifecycle and hence, if you use {caseinfo.Sales_Order__r.Status__c} directly on the template, you might run into undefined JS errors (causing the component to crash).

Note: This is only a sample assuming that you are returning a single sobject from the apex method. So, if you were to return a List, this code would need to be updated. Also, in the wired function, handle the error accordingly so that there is some graceful indication in the template.

0

There is another way in which you don't require to write apex to fetch data in LWC. You can rely on LDS to fetch the records.

You can use getRecord from lightning/uiRecordApi to fetch the records. Please check the example here

So if your requirement is to just fetch data then the ideal way is to use these standard wired services to get it. Use apex only when you have some complex business logic to perform. Hence, to retrieve parent record from the case record the code will be

import { LightningElement, wire, api } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import SALES_ORDER_FIELD from '@salesforce/schema/Case.Sales_Order__c';
import SALES_ORDER_ID from '@salesforce/schema/Case.Sales_Order__r.Id';
export default class OrderCaseViz extends LightningElement {
     @api recordId;
     @wire(getRecord, { recordId: '$recordId', fields: [SALES_ORDER_ID, INDUSTRY_FIELD]})
     case;

}

Now to access direct this field in template directly it will be like {case.data.Sales_Order__r.Id} or use a getter method and use getFieldValue as below

get parentRec() {
    return getFieldValue(this.case.data, SALES_ORDER_ID);
}
5
  • This option does not seem to work - the fields import SALES_ORDER_ID from '@salesforce/schema/Case.Sales_Order__r.Id'; are not being fetched.. Just getting Cannot read property 'Sales_Order__r' of undefined at runtime
    – erikvm
    Sep 10, 2020 at 6:44
  • Check if the API names of relationship Sales_Order__r is correct and the running user has atleast read access on the parent record's fields. Sep 10, 2020 at 7:49
  • I went with the ` @wire(caseData, {recordId: '$recordId'}) cases({ data, error }) { if (data) { console.log(data) } else if (error) { console.error(error); } } ` instead. When logging to the console, the values are there - but how do I render these to the template? Tried {cases.data.Sales_Order__r.Field_On_Order__c}, {Sales_Order__r.Field_On_Order__c} without success
    – erikvm
    Sep 10, 2020 at 7:53
  • Would I need to separately bind each value to the template? this.fieldOne = result.data.field_one; this.fieldTwo = result.data.field_two;?
    – erikvm
    Sep 10, 2020 at 7:58
  • You can go either way this.name = this.case.fields.Name.value; this.fieldtwo= this.case.fields.Sales_Order__r.Field_On_Order__c.value; or use getter to get values on the template. I think you are missing fields Sep 10, 2020 at 8:19

You must log in to answer this question.

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