lazy loading sfdcMonkey

How To Implement Infinity Or Lazy Loading In Salesforce Lightning DataTable

Lightning Component

Hi guys welcome back, Today in this post we are going to learn how we can implement infinity or lazy loading in salesforce ‘lightning:datatable’ lightning component using offset feature.

lazy loading lightning datatble

From developer console >> file >> new >> Apex Class

Apex Class : AccountTableController.apxc
/*
* Date : 3/4/2019
* API : 45
* Source : sfdcMonkey.com
*/
public class AccountTableController {
    
    //To return initial account records
    @AuraEnabled
    public static AccountWrapper getAccountRecords(Integer initialRows){
        AccountWrapper accountWrapper= new AccountWrapper();
        try{
            accountWrapper.accountsList = [SELECT ID,Name,Rating,AccountSource FROM Account ORDER BY Name ASC LIMIT :initialRows OFFSET 0];
            accountWrapper.totalRecords = [SELECT COUNT() FROM Account];
            accountWrapper.message = 'Account records are loaded';
            accountWrapper.success = true;
        }
        catch(Exception e){
            accountWrapper.message = e.getMessage();
            accountWrapper.success = false;
        }
        return accountWrapper;
    }
    
    //To return additional records based on offset
    @AuraEnabled
    public static List<Account> loadAccountRecords(Integer rowLimit,Integer rowOffset){
        return [SELECT ID,Name,Rating,AccountSource FROM Account ORDER BY Name ASC LIMIT :rowLimit OFFSET :rowOffset];
    }
    
    // wrapper class
    public class AccountWrapper{
        @AuraEnabled
        public Integer totalRecords = 0;
        @AuraEnabled
        public List<Account> accountsList = new List<Account>();
        @AuraEnabled
        public String message;
        @AuraEnabled
        public Boolean success;
    }
    
}

From developer console >> file >> new >> Lightning Component 

Lightning Component : infinityLoading.cmp
<!--
   Source : sfdcmonkey.com
   Date : 3/4/2019
   API : 45.0
-->
<aura:component controller="AccountTableController"
                implements="flexiPage:availableForAllPageTypes">
    
    <aura:handler name="init" value="{!this}" action="{!c.onInit}"/>
    
    <!--Aura Attributes START--> 
    <aura:attribute name="accountColums" type="List"/>
    <aura:attribute name="accountData" type="Object"/>
    <aura:attribute name="enableInfiniteLoading" type="Boolean" default="true"/>
    <aura:attribute name="initialRows" type="Integer" default="10"/>
    <aura:attribute name="currentCount" type="Integer" default="10"/>
    <aura:attribute name="totalRows" type="Integer" default="0"/>
    <aura:attribute name="loadOffset" type="Integer" default="1"/><!--Set when to trigger loading of more rows-->
    <!--Aura Attributes END--> 
    
    <div class="slds-page-header" role="banner">
        <span class="slds-page-header__title">Accounts List</span>
    </div>
    
    <!--Lightning data table markup-->
    <div style="height:250px">
        <lightning:datatable aura:id="dataTableID"
                             keyField="Id"
                             hideCheckboxColumn="true"
                             columns="{!v.accountColums}"
                             data="{!v.accountData}"
                             enableInfiniteLoading="{!v.enableInfiniteLoading}"
                             loadMoreOffset="{!v.loadOffset}"
                             onloadmore="{!c.handleLoadMore}"/>
    </div>
</aura:component>
JavaScript Controller : infinityLoadingController.js
/*
 * Date : 3/4/2019 * API : 45 
 * Source : sfdcMonkey.com 
*/
({
    onInit : function(component,event,helper){
        //Setting up colum information
        component.set("v.accountColums",
                      [
                          {
                              label : 'Name',
                              fieldName : 'accountName',
                              type : 'url',
                              typeAttributes:{label:{fieldName:'Name'},target:'_blank'}
                          },
                          {
                              label : 'Account Source',
                              fieldName : 'AccountSource',
                              type : 'text',
                          },
                          {
                              label : 'Rating',
                              fieldName : 'Rating',
                              type : 'text',
                          }
                      ]);
        // Call helper to set the data for account table
        helper.getData(component);
    },
    
    handleLoadMore : function(component,event,helper){
        if(!(component.get("v.currentCount") >= component.get("v.totalRows"))){
            //To display the spinner
            event.getSource().set("v.isLoading", true); 
            //To handle data returned from Promise function
            helper.loadData(component).then(function(data){ 
                var currentData = component.get("v.accountData");
                var newData = currentData.concat(data);
                component.set("v.accountData", newData);
                //To hide the spinner
                event.getSource().set("v.isLoading", false); 
            });
        }
        else{
            //To stop loading more rows
            component.set("v.enableInfiniteLoading",false);
            event.getSource().set("v.isLoading", false);
            var toastReference = $A.get("e.force:showToast");
            toastReference.setParams({
                "type":"Success",
                "title":"Success",
                "message":"All Account records are loaded",
                "mode":"dismissible"
            });
            toastReference.fire();
        }
    },
    
})
JavaScript Helper: infinityLoadingHelper.js
/*
 * Date : 3/4/2019
 * API : 45
 * Source : sfdcMonkey.com 
*/
({
    getData : function(component){
        // call apex class method
        var action = component.get("c.getAccountRecords");
        action.setParams({
            "initialRows" : component.get("v.initialRows") //how many rows to load during initialization
        });
        action.setCallback(this,function(response){
            var state = response.getState();
            var toastReference = $A.get("e.force:showToast");
            if(state == "SUCCESS"){
                var accountWrapper = response.getReturnValue();
                if(accountWrapper.success){
                    // set total rows count from response wrapper
                    component.set("v.totalRows",accountWrapper.totalRecords);  
                    
                    var accountList = accountWrapper.accountsList;
                    // play a for each loop on list of account and set Account URL in custom 'accountName' field
                    accountList.forEach(function(account){
                        account.accountName = '/'+account.Id;
                    });
                    // set the updated response on accountData aura attribute  
                    component.set("v.accountData",accountList);
                    // display a success message  
                    toastReference.setParams({
                        "type" : "Success",
                        "title" : "Success",
                        "message" : accountWrapper.message,
                        "mode" : "dismissible"
                    });
                    toastReference.fire();
                }
                else{ // if any server side error, display error msg from response
                    toastReference.setParams({
                        "type" : "Error",
                        "title" : "Error",
                        "message" : accountWrapper.message,
                        "mode" : "sticky"
                    }); 
                    toastReference.fire();
                }
            }
            else{ // if any callback error, display error msg
                toastReference.setParams({
                    "type" : "Error",
                    "title" : "Error",
                    "message" : 'An error occurred during Initialization '+state,
                    "mode" : "sticky"
                });
                toastReference.fire();
            }
        });
        $A.enqueueAction(action);
    },
    
    loadData : function(component){
        return new Promise($A.getCallback(function(resolve){
            var limit = component.get("v.initialRows");
            var offset = component.get("v.currentCount");
            var totalRows = component.get("v.totalRows");
            if(limit + offset > totalRows){
                limit = totalRows - offset;
            }
            var action = component.get("c.loadAccountRecords");
            action.setParams({
                "rowLimit" :  limit,
                "rowOffset" : offset
            });
            action.setCallback(this,function(response){
                var state = response.getState();
                var newData = response.getReturnValue();
                // play a for each loop on list of new accounts and set Account URL in custom 'accountName' field
                newData.forEach(function(account){
                    account.accountName = '/'+account.Id;
                });
                resolve(newData);
                var currentCount = component.get("v.currentCount");
                currentCount += component.get("v.initialRows");
                // set the current count with number of records loaded 
                component.set("v.currentCount",currentCount);
            });
            $A.enqueueAction(action);
        }));
    }
})

Check code comments.

Infinity Loading Component Output :

lazy loading lightning datatble

 

Related Resources :

Other popular Post :

Like our facebook page for new post updates. & Don’t forget to bookmark this site for your future reference.

if you have any suggestions or issue with it, you can post in comment box.

Happy Learning ?

About The contributor: 

Kiran.B

3 Post Contribute

kiran b sfdcMonkey

I have 3.5 years of experience and working in lightning for the past 1 year. I am working as a developer in Deloitte.

Skills : Apex ,lightning , visualforce,sales cloud,JavaScript,Einstein analytics

 

 

Post By Kiran :

  1. How To Implement Infinity Or Lazy Loading In Salesforce Lightning DataTable
  2. How To Implement Column Sorting In Salesforce Lightning DataTable
  3. Develop a Simple To-Do List App With Salesforce Lightning Component

    2 comments

    • This is giving error as

      Error in $A.getCallback() [Cannot read property ‘setParams’ of undefined] Callback failed: apex://AccountTableController/ACTION$getAccountRecords Failing descriptor: {c:infinityLoading}

      Please help.

      Thank you!

    • I am getting following error,Please help.

      Error in $A.getCallback() [Cannot read property ‘setParams’ of undefined] Callback failed: apex://AccountTableController/ACTION$getAccountRecords Failing descriptor: {c:infinityLoading}

    Leave a Reply