5

I have two different @wire methods that are calling Apex methods to get different results from two different objects.

After this information has been retrieved by each @wire respectively, I'd like to afterwards compare the results and set a few other attributes on the page.

How do I achieve this? Should I use connectedCallback() or renderedCallback() or neither?

Is there a better way to do multiple Apex method calls then process them afterwards within the JS when the component loads?

I'm hoping there's a graceful way to accomplish this in LWC without having to chain Promises, or having to handle all of this within a single Apex method call.

7

Option 1: use wire handlers. Instead of writing an Attribute name, you can write a function, and store the data in attributes, then call a common function when both results are available.


Example

attr1;
attr2;
@wire(getAttr1, {})
attr1result({data,error}) {
  if(data) {
    this.attr1 = data;
    if(this.attr1 && this.attr2) {
      this.doProcessing();
    }
  } // ... errors ... //
}
@wire(getAttr2, {})
attr2result({data,error}) {
  if(data) {
    this.attr2 = data;
    if(this.attr1 && this.attr2) {
      this.doProcessing();
    }
  } // ... errors ... //
}
doProcessing() {
  // do something with attr1 and attr2 //
}

Option 2: Use a promise chain. When calling them in order, keep in mind that this will cause a minor performance penalty.


connectedCallback() {
  getAttr1({}).then(result => {
    this.attr1 = result;
    return getAttr2({})
  }).then(result => {
    this.attr2 = result;
  }).finally(()=>this.doProcessing());
}
  • For option 1 - I'm currently using wire handlers for both to store data in attributes, but where/how do I call that common function right afterwards to leverage all the stored data, with the confidence that the data has already been fetched by both wires? – Brian Miller Feb 24 at 21:39
  • 3
    @BrianMiller I was mobile, so couldn't really write code (I tried, honest!). Now that I'm back, I edited in what I meant as a code example. – sfdcfox Feb 24 at 22:39
  • 1
    A brave man - wouldn't have dreamt to code while mobile! Doing a simple if check on both properties...totally makes sense, thank you! – Brian Miller Feb 24 at 22:44
  • Why not just create third apex method which directly returns the response based on other 2 apex methods? You can pass required parameters to this method itself? – salesforce-sas Feb 25 at 3:22
  • 1
    @javanoob Basically, yes. – sfdcfox Mar 1 at 23:55
3

We can chain wire services by using properties that are both dynamic and reactive by using it as $properties and also decorating it with track.

In the below example I have chained getObjectInfo and getPicklistValues wire services in a manner in which I leverage the data from getObjectInfo into getPicklistValues

import {
    LightningElement,
    api,
    wire,
    track
} from 'lwc';
import {
    getObjectInfo
} from 'lightning/uiObjectInfoApi';
import {
    getPicklistValues
} from 'lightning/uiObjectInfoApi';

export default class PocPicklistFilters extends LightningElement {

    // Flexipage provides recordId and objectApiName
    // to be passed from calling component
    @api objectApiName = 'Account';
    @api picklistField = 'Account.Industry';
    defaultRecordTypeId; //Master  Record Type Id
    @track options = [];


    @wire(getObjectInfo, {
        objectApiName: '$objectApiName'
    })
    wiredObjectInfo({
        error,
        data
    }) {
        if (data) {
            console.log('ObjectInfo' + JSON.stringify(data));
            this.record = data.recordTypeInfos;
            this.defaultRecordTypeId = data.defaultRecordTypeId;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.record = undefined;
        }
    }

    @wire(getPicklistValues, {
        recordTypeId: '$defaultRecordTypeId',
        fieldApiName: '$picklistField'
    })
    wiredPicklistInfo({
        error,
        data
    }) {
        if (data) {
            console.log('picklist' + JSON.stringify(data.values));
            this.processPicklistRawJSON(data.values);
        } else if (error) {
            console.log(JSON.stringify(error));
        }
    }

    processPicklistRawJSON(_rawData) {
        this.options = _rawData.map(row => {
            return {
                label: row.label,
                value: row.value
            };
        });
        console.log('picklistprocessed' + JSON.stringify(this.options));
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.