1

I have a hidden lightning component on a Lightning page that checks some data of the record and updates the record if needed. The record is a SBQQ__Quote__c record.

It mostly works, however, sometimes the record loads with cached (i.e. stale) data instead of the most recent data. Here is the code in the component:

<aura:component implements="force:hasRecordId,force:hasSObjectName,force:lightningQuickActionWithoutHeader,flexipage:availableForAllPageTypes" access="global" controller="SBQQ_CheckLineItems">
    <!-- This is a hidden component on the SBQQ__Quote__c page used to check that GSA Line Item Descriptions comply with the rules -->

    <aura:attribute name="record" type="Object"/>
    <aura:attribute name="simpleRecord" type="Object"/>
    <aura:attribute name="recordError" type="String"/>

    <force:recordData aura:id="recordLoader"
                      recordId="{!v.recordId}"
                      layoutType="FULL"
                      fields="SBQQ__ExpirationDate__c,Warning__c,QLE_Run__c"
                      mode="VIEW"
                      targetRecord="{!v.record}"
                      targetFields="{!v.simpleRecord}"
                      targetError="{!v.recordError}"
                      recordUpdated="{!c.doInit}"
                      />
</aura:component>

I've tried keying off of the event type, but it is just telling me it is Loaded.

var eventParams = event.getParams();
if(eventParams.changeType === "LOADED") {
   // force the reload while skipping the cache
   // this puts me in infinite loop
}

I've tried forcing a reloadRecord method and skipping the cache as documented here: https://developer.salesforce.com/docs/component-library/bundle/force:recordData/specification

The problem is this creates an infinite loop of loading. Is there anyway to detect if the load is from the cache or from the server?

Thanks,

Mike

  • Why you don't use Lightning:recordform instead of force:recorddata ? – sanket kumar May 8 at 2:57
  • Lightning:recordform displays on the GUI which I don't want. force:recorddata allows me to retrieve data without displaying anything which is what I want. – Mike Paisner May 8 at 18:40
0

In case anyone is experiencing similar problems, I finally found a solution to the stale data issue in lightning. This is currently being tested in Summer '19 preview.

The general approach is to retrieve information both through force:recordData (which represents what is displayed to the user) and through a traditional apex call (what is in the database). If there is a difference, then stale data is being displayed and force a refresh. I use a Javascript Promise to make sure the everything is executed sequentially. This is still undergoing testing, but initial smoke testing looks promising.

In a hidden component on the lightning page, I have the code below. Hope this helps someone.

Component Code:

<aura:component implements="force:hasRecordId,force:hasSObjectName,force:lightningQuickActionWithoutHeader,flexipage:availableForAllPageTypes" access="global" controller="SBQQ_CheckLineItems">
    <!-- This is a hidden component on the SBQQ__Quote__c page -->

    <aura:attribute name="record" type="Object"/>
    <aura:attribute name="simpleRecord" type="Object"/>
    <aura:attribute name="recordError" type="String"/>

    <force:recordData aura:id="recordLoader"
                recordId="{!v.recordId}"
                layoutType="FULL"
                fields="SBQQ__Status__c,SAP_Priced_Backend__c"
                mode="EDIT"
                targetRecord="{!v.record}"
                targetFields="{!v.simpleRecord}"
                targetError="{!v.recordError}"
                recordUpdated="{!c.doInit}"
                />

</aura:component>

In Controller:

({
    doInit : function(component, event, helper) {
        helper.performReload(component, event, helper);
        // do other stuff here...
    }
})

In Helper:

({
    performReload: function(component, event, helper) {
        var loadedRecordSAPPriced = component.get("v.simpleRecord.SAP_Priced_Backend__c");
        var loadedRecordStatus = component.get("v.simpleRecord.SBQQ__Status__c");
        var retrieveQuoteAction = component.get("c.getQuote");
        var recId = component.get("v.recordId");
        var retrieveQuoteParams = { "qId" : recId.toString() };
        retrieveQuoteAction.setParams(retrieveQuoteParams);
        var retrieveQuotePromise = helper.executeAction(component,retrieveQuoteAction);
        retrieveQuotePromise.then (
            $A.getCallback(function(response){
                debugger;
                if (loadedRecordSAPPriced != null && loadedRecordStatus != null && (response.SAP_Priced_Backend__c != loadedRecordSAPPriced || response.SBQQ__Status__c != loadedRecordStatus))     // this indicates cached version that got loaded is different than what is in database
                {
                    component.find('recordLoader').reloadRecord(true);
                }
            })
        ).catch();
    },

    executeAction: function(cmp,action,callback) {
        return new Promise(function(resolve,reject) {
            action.setCallback(this, function(response) {
                debugger;
                var state = response.getState();
                if (state==="SUCCESS") {
                    var retVal=response.getReturnValue();
                    resolve(retVal);
                } else if (state==="ERROR") {
                    var errors = response.getError();
                    if(errors) {
                        if(errors[0]&& errors[0].message) {
                            reject(Error("Error message: " + errors[0].message));
                        }
                    } else {
                        reject(Error("Unknown error"));
                    }
                }
            });
            $A.enqueueAction(action);
        });
    }
})

In Apex Class:

    @AuraEnabled
    public static SBQQ__Quote__c getQuote(Id qId)
    {
        List<SBQQ__Quote__c> qtList = [SELECT Id, QLE_Run__c, SBQQ__ExpirationDate__c, Warning__c, SAP_Priced_Backend__c, SBQQ__Status__c FROM SBQQ__Quote__c WHERE ID =: qId LIMIT 1];
        if (qtList.size() == 0) return null;
        SBQQ__Quote__c qt = qtList[0];
        return qt;
    }

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.