TransWikia.com

LWC Wire Over Multiple Objects - Summer '20 Behaviour Change

Salesforce Asked by BrBarr on October 4, 2021

I have used code similar to this in my current production org. The fields array contains multiple objects to pass in to the @wire service.

const fields = [
  "Opportunity.External_Id__c",
  "Account.External_Id__c",
  "Contact.External_Id__c",
  "Case.External_Id__c"
];

export default class LightningComponentTest extends LightningElement {
  @api recordId

  @wire(getRecord, { recordId: "$recordId", fields })
  displayedRecord({ data, error }) {
    if (data) {
      do something ...
    }
  }
}

Prior to Summer ’20, this would work fine and the wire service consistently returned the proper fields. This allowed us to reuse componentry across multiple objects and it was wonderful. After Summer ’20, we get the following error using this approach:

The "fields" query string parameter contained object api names that do not correspond to the api names of any of the requested record ids. The requested object api names were: [Account, Case, Contact, Opportunity], while the requested records had object types: [Account]

Is this an expected behaviour change? To me, this reads error message reads like a bug.

Does anyone have a suggestion on how to use the wire service to query across multiple objects, making it reusable? In this example, we have the same field name across multiple objects but having different field names would be useful as well, I just don’t recall if I ever used it.

I have seen approaches similar to this where you use the object context but when setting the component configuration in the lightning page editor, you get an error about using {!objectApiName}.

One Answer

Personally I would say it was a bug that this worked before. Are you aware that the fields array does not need to be a constant and can be dynamically generated? Here I do this, just to get the correct object's external ID (see the documentation for how and when an implicit objectApiName can be used, similar to recordId):

export default class LightningComponentTest extends LightningElement {
  @api recordId;

  @api get objectApiName() {
    return this._objectApiName;
  }

  set objectApiName(apiName) {
    this._objectApiName = apiName;

    // Now we have the API name we can generate the required fields array
    this.fields = [ apiName + ".External_Id__c" ];
  }

  // Tracked to make the getRecord reactive to changes
  @track fields;

  // Private property to hold the objectApiName API property value. This
  // declaration isn't strictly necessary but I like to do it so I can add JSDoc for it
  // normally (not here though)
  _objectApiName;

  @wire(getRecord, { recordId: "$recordId", fields: "$fields" })
  receiveRecord({ data, error }) {
    if (data) {
      do something ...
    }
  }
}

BTW, for contexts that don't directly support the implicit objectApiName, you can always explicitly expose this API property as a target config property in the component's meta XML (assuming this is an exposed component) and then provide the required, fully qualified object API name manually in the properties defined in the Lighting App Builder for the component usage in the page.

Answered by Phil W on October 4, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP