Exploring Lazy Loading Techniques in Lightning Web Components (LWC) A Comprehensive Guide

Exploring Lazy Loading Techniques in Lightning Web Components (LWC): A Comprehensive Guide

Introduction

In LWC, lazy loading can be implemented using server-side Apex or client-side JavaScript. It can be combined with either HTML tables or Lightning Datatable components. This guide explores four approaches, their unique features, trade-offs, and high-level implementation strategies.

Unified Interaction Patterns: Scroll Bar vs. Load More Button

Before diving into implementation methods, let’s explore the two interaction patterns that drive lazy loading:

a) Scroll Bar (Infinite Scrolling)

  • Seamless Experience: Automatically loads data as the user scrolls, eliminating manual actions.
  • Real-Time Data Flow: Ideal for applications requiring continuous data updates (e.g., social feeds).
  • Potential Drawbacks: Risk of over-fetching data and complex scroll position tracking.

b) Load More Button

  • Explicit Control: Users decide when to load additional data, reducing unnecessary server calls.
  • Predictable Performance: Simplifies error handling and resource management.
  • Potential Drawbacks: Requires user interaction, which may disrupt browsing flow.

Regardless of the underlying method (server-side or client-side, HTML table or datatable), two common interaction patterns are used to trigger lazy loading:

We will see below 4 approaches and their sample LWC component to implement the lazy loading –

  • Server-Side with HTML Table & Apex
  • Server-Side with Lightning Data Table & Apex
  • Client-Side with HTML Table & Apex
  • Client-Side with Lightning Data Table & Apex

Pros and Cons Comparison

MethodProsCons
1. Server + HTML Table
• Full control over UI design.
• Scalable for large datasets.
• Reduces client resource usage.
Manual DOM updates for new data.
Increased server load due to frequent API calls.
Requires Apex controllers for data fetching.
2. Server + Lightning Data TableBuilt-in features (sorting).
Server-efficient for large data.
Native Salesforce integration.
Limited UI customization (constrained by Salesforce LWC framework).
Requires Apex controllers for data fetching.
3. Client + HTML TableInstant navigation after initial load.
No post-load server calls.
Poor performance with large datasets.
Long initial load time.
Browser memory issues.
4. Client + Lightning Data TableRich interactivity (client-side sorting/filtering).
Pre-built UI components.
Client memory limitations for large data.
No server-side filtering/sorting after initial load.

🌐 Server Side Lazy Loading Techniques –

1. Server-Side Lazy Loading with HTML Table & Apex

Features –
  • Data Source: Apex methods fetch paginated data using OFFSET and LIMIT SOQL clauses.
  • UI Component: Custom HTML table built with <table> and LWC directives like for:each.
  • Triggers:
    • Scroll: Track scroll position via JavaScript to fetch the next chunk.
    • Load More: Increment the page counter on button click.
  • Use Case: Large datasets requiring server-side filtering and lightweight UI.
High-Level Implementation Approach
  • Apex: Create a method with @AuraEnabled to return paginated data using LIMIT and OFFSET .
  • LWC: Track page numbers and using imperative calls to fetch data.
  • UI: Render rows dynamically in the HTML table. For scroll, calculate scroll position via javascript.
a) Example – Server Side Lazy Loading In HTML Table With Scroll Bar

This LWC example demonstrates lazy loading functionality in a HTML table using scroll bar. The component displays contact records. It fetches more data from the server as users scroll the table. The next set of records is appended in the table.

Demo –

High-Level Code Explanation

  • HTML File
    • Lightning Card: Wraps the table in a styled container with a title and icon.
    • Scrollable Html Table: Displays contact data in a table with the following features:
      • Sticky Header: Ensures the header remains visible during scrolling.
      • Dynamic Data: Rows are populated using the contacts property.
      • Serial Numbers: Adds a serial number column for each contact.
    • Loading Spinner: Displays a spinner and a “Loading contacts…” message when the isLoading flag is true.
    • Load More on Scroll Bar:
      • Visibility: Lazy load contacts based on page size. Displays “All contacts loaded” when no more records are available.
    • Back to Top Button:
      • Positioning: Placed at the bottom-right corner.
      • Visibility: Controlled dynamically based on scroll position.
      • Action: Smoothly scrolls the page to the top when clicked.
  • JavaScript File
    • Properties
      • contacts: Stores the list of contact records retrieved from the server.
      • pageSize: Defines the number of records fetched per server call (default is 5).
      • offset: Tracks the starting index for the next batch of records(default is 0).
      • isLoading: Indicates whether a data-fetching operation is in progress.
      • hasMoreRecords: Signals whether there are additional records to load.
    • Methods
      1. connectedCallback
        • Automatically called when the component is inserted into the DOM.
        • Fetches the initial batch of contacts by invoking loadInitialData.
      2. loadInitialData
        • Fetches data from the server using the getContacts Apex method.
        • Appends new contacts to the contacts array
        • Updates the offset for the next batch and toggles the hasMoreRecords flag based on the server response.
        • Capture errors if the Apex call fails.
      3. loadingDelay
        • Introduces a 1-second delay to mimic real-world API behavior and improve UX.
      4. loadMoreData
        • Triggered By Scroll events or manual user action.
        • Fetches the next batch of records by invoking loadInitialData.
      5. allLoaded
        • A getter to check if all records have been loaded.
        • Returns true if hasMoreRecords is false and there are loaded contacts.
      6. processcontacts
        • Adds serial numbers to each contact for display.
        • Uses the current length of contacts to calculate the serial number.
      7. handleScroll
        • Scroll Monitoring: Detects when the user scrolls near the bottom of the container and triggers loadMoreData.
        • Back to Top Button Toggle: Displays or hides the button based on the scroll position.
      8. scrollToTop
        • Scrolls the container to the top for better navigation.
      9. setScrollableHeight
        • Calculates and sets the height of the scrollable container based on the number of visible rows.
Sample Code –
b) Example – Server Side Lazy Loading In HTML Table With Load More Button

This LWC example demonstrates lazy loading functionality in a HTML table with a “Load More” button. The component displays contact records. It fetches more data from the server as users click on the “Load More” button. It appends the next set of records in the table.

  1. The LWC loads an initial set of contacts from the server using the getContacts Apex method. The number of records loaded is determined by the pageSize property.
  2. The LWC processes the loaded contacts by adding a serial number to each contact and then updates the tracked contacts property to reflect the changes.
  3. The LWC allows users to load additional contacts by clicking the “Load More” button. It uses the offset property to determine the starting point for the next set of records, ensuring that data is fetched efficiently from the server.
  4. The LWC dynamically updates the scrollable container’s content by appending new rows while ensuring the scroll bar reflects the total number of loaded records.
  5. The LWC includes a “Back to Top” button that becomes visible when the user scrolls down. This button allows users to quickly scroll back to the top of the table for better navigation.
Demo –
Sample Code –

2. Server-Side Lazy Loading with Lightning Data table & Apex

Features –
  • Data Source: Paginated data from Apex, similar to the HTML table approach.
  • UI Component: Built-in lightning-datatable with sorting, styling, and column customization.
  • Triggers:
    • Scroll: Use the onloadmore event or custom scroll listeners.
    • Load More: Update the datatable’s data property on button click.
  • Use Case: Applications needing a feature-rich table with server-managed data.

High-Level Implementation Approach

  • Apex: Create a method with @AuraEnabled to return paginated data using LIMIT and OFFSET .
  • LWC: Use lightning-datatable and bind columns/data. For scroll, use onloadmore or custom logic; for the button, update the Datatable’s data property.

Below are key attributes and events in Lightning Datatable that enable lazy loading:

  1. enable-infinite-loading:
    • Enables lazy loading.
    • Loads more data when the user scrolls to the end of the table.
    • Works with the onloadmore event to fetch additional data.
  2. load-more-offset:
    • Determines how close the user must scroll to the bottom to trigger loading.
    • Default value: 20 pixels from the bottom.
  3. onloadmore:
    • Event handler that triggers when more data needs to be loaded.
    • This is where the logic for fetching additional records is implemented.
a) Example – Server Side Lazy Loading In Lightning Data Table With Scroll Bar

This LWC example demonstrates lazy loading in a Lightning Datatable with scroll bar. The component displays account records in a scrollable table, fetching more data from the server as users scroll down.

Demo –
High-Level Code Explanation

This example demonstrates lazy loading in a Lightning Datatable. The component displays account records in a scrollable table, fetching more data from the server as users scroll down.

HTML File
  • Lightning Card: Wraps the datatable in a styled container with a title and icon.
  • Lightning Datatable: Displays the account data with the following features:
    • enable-infinite-loading: Enables lazy loading.
    • onloadmore: Calls the JavaScript method to fetch additional records.
    • hide-checkbox-column and show-row-number-column: Customize the appearance.
  • Status Messages: Inform users whether data is loading or if all records are loaded.
JavaScript File
  • Properties:
    • accounts: Stores account data.
    • columns: Defines the table’s columns (e.g., Name, Rating).
    • pageSize: Determines the number of records fetched per server call (default is 5).
    • offset: Tracks the starting index for the next batch of records (default is 0).
    • hasMoreRecords: Indicates if there are additional records to load.
    • loadMoreStatus and isLoading: Track loading progress and display messages.
  • Methods:
    1. connectedCallback:
      • Invoked when the component is loaded.
      • Fetches the initial set of account data by invoking the loadData method.
    2. loadData:
      • Core method for fetching data using the Apex method getAccounts.
      • Updates accounts with new records and adjusts the hasMoreRecords flag based on the server response.
      • Dynamically adjusts the height of the scrollable container to improve user experience.
    3. loadMoreData:
      • Called when the user scrolls to the bottom of the table.
      • Fetches the next set of records and appends them to accounts.
    4. allLoaded:
      • A getter that checks if all records have been loaded.
    5. setScrollableHeight:
      • Dynamically sets the scrollable container’s height to fit the visible rows.
Sample Code –
b) Example – Server Side Lazy Loading In Lightning Data Table With Load More Button

This LWC example demonstrates lazy loading in a Lightning Datatable with a “Load More” button.. The component displays account records in a data table, fetching more data from the server as users click on load more buttom.

Demo –
High-Level Code Explanation
HTML File
  • Lightning Card
    Wraps the datatable in a styled container with a title and icon (standard:account). This provides a clean and visually appealing header for the component.
  • Lightning Datatable
    Displays the account data with the following features:
    • Key Fields: Identifies records by their unique ID.
    • hide-checkbox-column and show-row-number-column: Customizes the table appearance by removing checkboxes and adding row numbers.
    • Dynamic Data: Data is dynamically populated via the accounts property.
    • Columns: Defined using the columns property.
  • Loading Spinner
    Displays a spinner and a “Loading accounts…” message when the isLoading flag is true.
  • Load More Button
    Includes the following behaviors:
    • Visible When Applicable: Displays if more data can be loaded (hasMoreRecords is true).
    • Hides When All Data Loaded: Displays “All accounts loaded” when all data is fetched.
  • Back to Top Button
    • Positioning: Placed at the bottom-right corner.
    • Visibility: Becomes visible when the user scrolls down.
    • Action: Smoothly scrolls the page to the top when clicked.
JavaScript File
  • Properties
    • accounts: Tracks the account data displayed in the datatable.
    • columns: Defines the table columns (e.g., “Account Name” and “Industry”).
    • pageSize: Determines the number of records fetched per server call (default is 5).
    • offset: Tracks the starting index for the next batch of records (default is 0).
    • isLoading: Indicates whether a data-fetching operation is in progress.
    • hasMoreRecords: Indicates if there are additional records to load.
  • Methods
    1. connectedCallback
      • Invoked when the component is loaded.
      • Fetches the initial set of account data by invoking the loadData method.
    2. loadData
      • Core method for fetching data using the Apex method getAccounts.
      • Appends new records to the accounts array.
      • Updates the offset for the next batch and toggles the hasMoreRecords flag based on the server response.
      • Capture errors if the Apex call fails.
    3. loadingDelay
      • Introduces a 1-second pause to mimic real-world API behavior and enhance UX.
    4. handleLoadMore
      • Triggered By clicking the “Load More” button.
      • Calls loadData to fetch the next batch of records.
    5. handleScrollEvent
      • Adds an event listener to detect scroll activity.
      • Displays or hides the scroll to top button based on the scroll position.
    6. scrollToTop
      • Scrolls the page back to the top using a smooth animation.
    7. allLoaded
      • A getter to determine if all records are loaded.
      • Returns true if no more records are available (hasMoreRecords is false) and some data has already been loaded.
Sample Code –

🖥️Client Side Lazy Loading Techniques –

1. Client-Side JavaScript with HTML Table

Features –
  • Data Source: Entire dataset fetched initially, split into chunks using JavaScript.
  • UI Component: Dynamic HTML table with client-side row rendering.
  • Triggers:
    • Scroll: Track scroll position to render the next chunk.
    • Load More: Increment visible rows on button click.
  • Use Case: Small datasets where client-side processing is acceptable.
High-Level Implementation Approach
  • Data Fetching: Retrieve all data upfront and store it in a JavaScript array.
  • Chunking: Slice data into segments using Array.slice().
  • UI: Render initial segment. For scroll, add event listeners to load the next chunk; for the button, increment the visible row count.
a) Example – Client Side Lazy Loading In HTML Data Table With Scroll Bar

This LWC example demonstrates lazy loading functionality in a HTML table using scroll bar. The component displays contact records. It fetches more data from the server as users scroll the table. The next set of records is appended in the table.

High-Level Code Explanation
  • HTML File
    • Lightning Card
      Wraps the entire component in a styled container with the title “Client Side Lazy Loading In HTML Table With Scroll Bar – LWC” and the standard:contacts icon. Provides a consistent Salesforce UI shell for the feature.
    • Scrollable Html Table: Displays contact data in a table with the following features:
      • Sticky Header: Ensures the header remains visible during scrolling.
      • Dynamic Data: Rows are populated using the contacts property.
      • Serial Numbers: Adds a serial number column for each contact.
    • Loading Spinner: Displays a spinner and a “Loading contacts…” message when the isLoading flag is true.
    • Load More on Scroll Bar:
      • Visibility: Lazy load contacts based on page size. Displays “All contacts loaded” when no more records are available.
    • Back to Top Button:
      • Positioning: Placed at the bottom-right corner.
      • Visibility: Controlled dynamically based on scroll position.
  • JavaScript File
    • Properties
      • contacts: Stores the list of contact records retrieved from the server.
      • pageSize: Defines the number of records fetched per server call (default is 5).
      • offset: Tracks the starting index for the next batch of records (default is 0).
      • isLoading: Indicates whether a data-fetching operation is in progress.
    • Methods
      1. connectedCallback
        • Automatically called when the component is inserted into the DOM.
        • Fetches the initial batch of contacts by invoking loadInitialData.
      2. loadInitialData
        • Fetches data from the server using the getAllContacts Apex method.
        • Processes and appends new contacts to the contacts array.
        • Updates the offset for the next batch and toggles the hasMoreRecords flag based on the response.
        • Captures and handles errors if the Apex call fails.
      3. loadingDelay
        • Introduces a 1-second delay to mimic real-world API behavior and improve UX.
      4. loadMoreData
        • Triggered by scroll events when nearing the bottom or by manual user action.
        • Invokes loadInitialData to fetch the next batch of records.
      5. allLoaded
        • A getter to check if all records have been loaded.
        • Returns true if hasMoreRecords is false and there are loaded contacts.
      6. processContacts
        • Adds serial numbers to each contact for display.
        • Uses the current length of contacts to calculate the serial number.
      7. handleScroll
        • Scroll Monitoring: Detects when the user scrolls near the bottom of the container and triggers loadMoreData.
        • Back to Top Button Toggle: Displays or hides the button based on the scroll position.
      8. scrollToTop
        • Scrolls the container to the top for better navigation.
      9. setScrollableHeight
        • Calculates and sets the height of the scrollable container based on the number of visible rows.
Sample Code –

2. Client-Side JavaScript with Lightning Datatable

Features –
  • Data Source: Full dataset loaded upfront, paginated via JavaScript.
  • UI Component: lightning-datatable with client-side data slicing.
  • Triggers:
    • Scroll: Dynamically update the datatable’s bound data on scroll.
    • Load More: Adjust the displayed dataset on button click.
  • Use Case: Moderate datasets requiring datatable features and client-side flexibility.
High-Level Implementation Approach
  • Data Handling: Load all data into the component and manage visibility via JS.
  • Triggers: Update the Datatable’s bound data property dynamically. For scroll, calculate thresholds; for the button, adjust the displayed dataset.

To be continues , code sample for Client Side, will share in new blog 🙂

Choosing the Right Approach

  • Prioritize server-side methods for large datasets or real-time data accuracy.
  • Opt for client-side methods if initial load time isn’t critical and datasets are small.
  • Use Datatable for standardized features, and HTML tables for custom designs.

Align your lazy loading strategy with your application’s data size. Consider UX goals and technical constraints. This way, you can strike the right balance between performance and usability.New chat

One response to “Exploring Lazy Loading Techniques in Lightning Web Components (LWC): A Comprehensive Guide”

  1. […] we refer to our previous blog, server side lazy loading, we used the offset approach in our apex class. However, it has the limitations listed […]

    Like

Leave a comment