1

I have a LWC Component which reads data from Account Object. This component is located in the detail page.

HTML:

<template>
   <lightning-layout vertical-align="center" class="large">
       <lightning-layout-item flexibility="auto" padding="around-small" size="12">
            <div id="inverse" class="row dark-background slds-text-heading_small slds-grid slds-wrap slds-grid_vertical-align-center">
            <lightning-icon icon-name="action:announcement" alternative-text="Connected" variant="inverse"
            title="medium (default)"></lightning-icon>
            <template if:true={account}>
            <div class="slds-grid slds-col slds-grid_align-center">Service Tier :   
                <span class="textcolor addspace">{CustomerTier}</span></div> 
            </template>    
        </div>
            </lightning-layout-item>
      </lightning-layout> 
</template>

JS:

import { LightningElement, api, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';

import CUSTOMER_TIER from '@salesforce/schema/Account.Customer_Tier__c';

const fields = [CUSTOMER_TIER];

export default class Metadata_AccountTierColorComponent extends LightningElement {
    @api recordId;
   
    @wire(getRecord, { recordId: '$recordId', fields })
    account;    
    get CustomerTier() {
        if(getFieldValue(this.account.data, CUSTOMER_TIER) != '' && getFieldValue(this.account.data, CUSTOMER_TIER) != null)
        return getFieldValue(this.account.data, CUSTOMER_TIER);
        else
        return 'None';
    }
}

The variable CustomerTier returns none in UI first and then the Actual customer tier on the Account. Guess the CustomerTier function is getting executed multiple times.

How do I ensure that component shows value only after the wire service returns account data?

3 Answers 3

2

The issue is getRecord getting called two times, the first one with undefined as recordId, so account is truthy.
Instead of a getter for customerTier you could define it as an instance variable which will be setted in a function decorated with @wire(getRecord)

HTML:

<template>
    <lightning-layout vertical-align="center" class="large">
        <lightning-layout-item flexibility="auto" padding="around-small" size="12">
            <div id="inverse" class="row dark-background slds-text-heading_small slds-grid slds-wrap slds-grid_vertical-align-center">
                <lightning-icon icon-name="action:announcement" alternative-text="Connected" variant="inverse"
                title="medium (default)"></lightning-icon>
                <template if:true={customerTier}>
                    <div class="slds-grid slds-col slds-grid_align-center">Service Tier :   
                        <span class="textcolor addspace">{customerTier}</span>
                    </div> 
                </template>    
            </div>
        </lightning-layout-item>
    </lightning-layout> 
</template>

JS:

import { LightningElement, api, wire } from 'lwc';
import { getRecord, getFieldValue } from 'lightning/uiRecordApi';

import CUSTOMER_TIER from '@salesforce/schema/Account.Customer_Tier__c';

const fields = [CUSTOMER_TIER];

export default class Metadata_AccountTierColorComponent extends LightningElement {
    @api recordId;
    customerTier;
   
    @wire(getRecord, { recordId: '$recordId', fields })
    fetchAccount({ data }) {
        if (data) { // this ensure that only when the real account data is retrieved customerTier will be setted
            this.customerTier = getFieldValue(this.account.data, CUSTOMER_TIER) || 'None';
        }
    }
}
2
  • You just proved the point in my answer, there's a number of ways to tackle the problem, depending on one's preferences.
    – sfdcfox
    Apr 22, 2022 at 17:12
  • @sfdcfox Fully agree.
    – RubenDG
    Apr 22, 2022 at 17:16
1

There's tons of ways to do this, but perhaps one of the easiest is to just write a method for that:

get isLoading() {
  return !this.account.data && !this.account.error;
}

Which you can then use in your template:

<lightning-spinner if:true={isLoading}></lightning-spinner>
<lightning-layout if:false={isLoading} ...
0

You should be able to do this by initializing in one method :

account; 

tier;

initialized;

    @wire(getRecord, {recordId: '$recordId',fields})
    populateData({data,error}) {
       if(data) {
              this.account = data;
              this.tier = getFieldValue(this.account,CUSTOMER_TIER); 
          if(!this.tier) {
            this.tier = 'None';
          }
        this.initialized = true;
      }
    }

and then in your component :

<template>
   <lightning-layout vertical-align="center" class="large">
       <lightning-layout-item flexibility="auto" padding="around-small" size="12">
            <div id="inverse" class="row dark-background slds-text-heading_small slds-grid slds-wrap slds-grid_vertical-align-center">
            <lightning-icon icon-name="action:announcement" alternative-text="Connected" variant="inverse"
            title="medium (default)"></lightning-icon>
            <template if:true={initialized}>
            <div class="slds-grid slds-col slds-grid_align-center">Service Tier :   
                <span class="textcolor addspace">{tier}</span></div> 
            </template>    
        </div>
            </lightning-layout-item>
      </lightning-layout> 
</template>

You must log in to answer this question.

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