TL;DR whats the best way to tell a page that the underlying data has loaded through a mix of imperative calls and wire calls, preferably without chaining .then
functions
Long Version:
I have 4 async requests that I want to perform before showing the page.
My first initial try was to have a <template if:true={loaded}>
tag to show the form when it's loaded and a <template if:false={loaded}>
tag to show a spinner while it's loaded. The loaded
property is actually a getter. However when I updated the three properties that hold the async data my getter doesn't get recalled
Html:
<template>
<template if:false={loaded}>
<lightning-layout>
<lightning-layout-item size="12" class="slds-text-align_center">
<div style="min-height: 100px;">
<lightning-spinner alternative-text="asset loading" size="large"></lightning-spinner>
</div>
</lightning-layout-item>
</lightning-layout>
</template>
<template if:true={loaded}>
<lightning-layout multiple-rows="true" padding="around-small">
<!--content-->
</lightning-layout>
</template>
</template>
Controller:
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import ASSET_OBJECT from '@salesforce/schema/Asset';
import CURRENCY_ISO_FIELD from '@salesforce/schema/Asset.CurrencyIsoCode';
import CHANNEL_MODE_FIELD from '@salesforce/schema/Asset.Channel_Mode__c';
@track
model;
@track
currencyPicklistValues;
@track
channelModePicklistValues;
@track
loaded;
@wire(getObjectInfo, {objectApiName: ASSET_OBJECT})
objectInfo
@wire(getPicklistValues, {recordTypeId: '$objectInfo.data.defaultRecordTypeId', fieldApiName : CURRENCY_ISO_FIELD})
wiredCurrencyPickLists({data}) {
if (data) {
this.currencyPicklistValues = data;
}
}
@wire(getPicklistValues, {recordTypeId: '$objectInfo.data.defaultRecordTypeId', fieldApiName : CHANNEL_MODE_FIELD})
wiredChannelPicklists({data}) {
if (data) {
this.channelModePicklistValues = data;
}
}
connectedCallback() {
getAssetModel({assetId: this.recordId})
.then(result => {
this.originalModel = JSON.parse(JSON.stringify(result));
this.model = result;
this.selectedRevision = result.revisions.find((revision) => {
return revision.majorRevision.Id === result.asset.Current_Major_Revision__c;
});
})
.catch(err => {
this.error = err;
});
}
get loaded() {
return this.model && this.currencyPickListValues && this.channelModePicklistValues;
}
Since get loaded
doesn't get called after the underlying properties change I attempted to use async/await
patterns and just set loaded
as a @track
property. However now I'm running into issues with wrapping @wire
properties in a promise.
Parsing error: Leading decorators must be attached to a class declaration (62:12)
I also can't call the wire methods imparatively otherwise I get an error
Imperative use is not supported. Use @wire(getObjectInfo).
connectedCallback() {
(async(that) => {
debugger;
const objectInfo = that.asyncWireRequest(getObjectInfo, {objectApiName: ASSET_OBJECT});
that.channelModePicklistValues = await that.asyncWireRequest(getPicklistValues, {recordTypeId: objectInfo.data.defaultRecordTypeId, fieldApiName : CHANNEL_MODE_FIELD});
that.currencyPicklistValues = await that.asyncWireRequest(getPicklistValues, {recordTypeId: objectInfo.data.defaultRecordTypeId, fieldApiName : CURRENCY_ISO_FIELD})
that.model = await that.asyncRequest(getAssetModel, {assetId : this.recordId});
that.originalModel = JSON.parse(JSON.stringify(that.model));
that.selectedRevision = that.revisions.find((revision) => {
return revision.majorRevision.Id === that.model.asset.Current_Major_Revision__c;
});
that.loaded = true;
})(this);
}
asyncImperativeRequest = (apexMethod, parameters) => {
return new Promise((accept, reject) => {
apexMethod(parameters)
.then(result => {
accept(result);
})
.catch(error => {
reject(error);
})
});
}
asyncWireRequest = (wireMethod, parameters) => {
return new Promise((accept, reject) => {
@wire(wireMethod, parameters)
wireHandler({error, data}) {
if (data) {
accept(data);
} else {
reject(error);
}
}
});
}
getPicklistValues
imperatively and wire-services are like self-invoked standard functions (type of) which cannot be put in other methods. – salesforce-sas Aug 23 '19 at 3:19