Infinite Loading in Data Table in Salesforce LWC

In this Salesforce tutorial, we will learn to implement infinite loading in the Salesforce LWC data table. The infinite loading of data in an LWC component is also termed lazy loading, and it loads data only when it becomes visible to the user as they scroll down the page, instead of loading everything at once when the page initially loads.

Infinite Loading in Salesforce Lightning Web Component

Infinite loading is used in Salesforce Lightning Web Components (LWC) to fetch and display more data dynamically as the user scrolls down. It is implemented in list views, data tables, or feeds to improve performance by loading data in parts instead of all at once.

Infinite loading in LWC initially loads a fixed number of records when the component is first rendered. As the user scrolls through the list, the component detects when they reach the bottom. At this point, it fetches the next set of records and appends them to the existing list, and it continues until all available data is loaded.

Implement Infinite Loading in the Salesforce LWC data table

In the example below, we will implement infinite loading in the LWC data table, where we will use the enable-infinite-loading and load-more-offset attributes of the Lightning Datatable.

The enable-infinite-loading attribute allows loading a subset of data initially and fetching more as users scroll to the end of the table. It is used along with the onloadmore event handler to retrieve additional data dynamically.

The load-more-offset attribute determines when infinite loading is triggered based on the table’s scroll position in the data table.

Now, follow the steps below to create an LWC data table with infinite or lazy loading.

1. First, we will create an Apex controller class using the offset method that will fetch the Opportunity records.

public with sharing class InfiniteLoadingController {
    @AuraEnabled(cacheable=true)
    public static List<Opportunity> getOpportunities(Integer limitSize, Integer offset){
        return [SELECT Id, Name, StageName, CloseDate
                FROM Opportunity
                ORDER BY CreatedDate
                LIMIT :limitSize
                OFFSET :offset];
    }
}

2. Create a lightning web component and enter the code below in the HTML file.

<template>
    <lightning-card title="Lazy loading DataTable">
    <div style="height:500px">
        <lightning-datatable key-field="Id"
                data={opportunities}
                columns={columns}
                enable-infinite-loading
                onloadmore={loadMoreData}
                hide-checkbox-column="true"
                show-row-number-column="true">
        </lightning-datatable> 
    </div>
</lightning-card>
</template>

3. After this, enter the code below in the LWC component’s JS file. This code will handle the logic of infinite loading of records in the data table.

import { LightningElement, track, wire } from 'lwc';
import getOpportunities from '@salesforce/apex/InfiniteLoadingController.getOpportunities';

const columns = [
    { label: 'Id', fieldName: 'Id', type: 'text' },
    { label: 'Name', fieldName: 'Name', type: 'text'},
    { label: 'Stage', fieldName: 'StageName', type: 'text'},
    { label: 'Close Date', fieldName: 'CloseDate', type: 'date'}
];

export default class LazyLoadingLWCDemo extends LightningElement {
    opportunities = [];
    error;
    columns = columns;
    rowLimit = 25;
    rowOffSet = 0;
  
    connectedCallback() {
        this.loadData();
    }

    loadData() {
        return getOpportunities({ limitSize: this.rowLimit, offset: this.rowOffSet })
        .then(result => {
            this.opportunities = [...this.opportunities, ...result];
            this.error = undefined;
        })
        .catch(error => {
            this.error = error;
            this.opportunities = undefined;
        });
    }

    loadMoreData(event) {
        const { target } = event;
        target.isLoading = true;
        this.rowOffSet += this.rowLimit;
        this.loadData().then(() => {
            target.isLoading = false;
        });
    }
}

In the above code, we implemented lazy loading by setting a rowLimit (25 records per fetch) and a rowOffSet (starting at 0). When the component loads, it calls loadData(), which fetches the first 25 records using the Apex method.

To fetch more data, the loadMoreData() method increases rowOffSet by 25 and calls loadData() again, retrieving the next batch of records. The new data is then appended to the existing list using the spread operator (…) without reloading the page.

4. Now, make the LWC component available on the Lightning page by entering the code below inside the tag LightningComponentBundle.

<isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>

5. Navigate to the lightning page and deploy the LWC component. To deploy the LWC data table on the lightning page, click the settings icon and select Edit page.

Then, in the Lightning App Builder, drag and drop the component to the page layout and save it.

Infinite loading of LWC data table in Salesforce

Now, you see the LWC data table is implemented with infinite loading. Here, the records will load when you scroll through the records in the data table.

Salesforce LWC data table with lazy loading

This way, we can implement infinite or lazy loading to a Salesforce Lightning data table in LWC.

Infinite Loading Error: NUMBER_OUTSIDE_VALID_RANGE

This error occurs when we call the Apex method in the LWC. We have used the OFFSET method in the apex class to fetch the opportunity records, but when we use offset to fetch more than 2000 records, it will return the following error in the LWC component:

Error : NUMBER_OUTSIDE_VALID_RANGE: Maximum SOQL offset allowed for apiName Opportunity is 2000

To resolve this error, instead of using OFFSET, we can implement lazy loading with an ID filter to handle large datasets. For example, we can define the SOQL of the controller class method as:

SELECT Id, Name, StageName, CloseDate
                FROM Opportunity
                WHERE Id > :lastOpportunityId
                ORDER BY Id LIMIT 100

This query retrieves the next 100 records after the specified lastOpportunityId and passes the last account ID to Apex from LWC.

Conclusion

In this Salesforce LWC tutorial, we learned how to implement the feature of infinite scrolling or lazy loading. In the above LWC code, we used attributes like enable-infinite-loading and load-more-offset in the lightning-datatable, along with an Apex controller to fetch data and implement infinite loading.

By implementing the lazy loading feature, we can reduce resource usage, improve page load speed, and enhance user experience by loading only necessary data at a time.

You may also like to read:

Agentforce in Salesforce

DOWNLOAD FREE AGENTFORCE EBOOK

Start with AgentForce in Salesforce. Create your first agent and deploy to your Salesforce Org.

Salesforce flows complete guide

FREE SALESFORCE FLOW EBOOK

Learn how to work with flows in Salesforce with 5 different real time examples.