11

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.

3 Answers 3

14

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());
}
7
  • 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? Feb 24, 2020 at 21:39
  • 4
    @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, 2020 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! Feb 24, 2020 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? Feb 25, 2020 at 3:22
  • 1
    @javanoob Basically, yes.
    – sfdcfox
    Mar 1, 2020 at 23:55
6

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));
    }
}
0

Using Promise.All

 import { LightningElement, wire,track } from 'lwc';
 import getPricebookInfo from '@salesforce/apex/StoreHandler.getPricebookInfo';
 import getSiteUrlInfo from '@salesforce/apex/StoreHandler.getSiteUrlInfo';

export default class ConfigGeneralSettings extends LightningElement {
   @track pricebookMap;
   @track siteMap;

connectedCallback(){
    Promise.all([getPricebookInfo(), getSiteUrlInfo()]).then((values) =>{
        console.log(values);
        this.pricebookMap = JSON.parse(values[0]);
        this.siteMap = JSON.parse(JSON.parse(values[1]).SiteOptionList);
    });
}
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

You must log in to answer this question.

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