Cursor with LWC

Cursor recently has been introduced, a powerful feature still in Beta. This new capability allows developers to efficiently handle large query result sets without loading the entire dataset into memory. With cursors, you can traverse query results in smaller parts. It offers the flexibility to navigate forward and backward through the results—a significant advantage for managing large-scale data.

Exploring Apex Cursors in LWC: A Game-Changer for Large Query Result Sets

If you’re working on Lightning Web Components (LWC) or planning to implement solutions requiring seamless handling of large datasets, this feature opens up exciting opportunities.

In this blog, we’ll showcase how to leverage Apex Cursor to fetch all contacts in an org and display them dynamically on a user-friendly UI using LWC. This practical implementation will demonstrate how you can efficiently work with large datasets while ensuring optimal performance and scalability.

Exploring Apex Cursors in LWC : Apex Cursors recently has been introduced, a powerful feature still in Beta.

Let us create component with name ProcessLargeDataset and apex class named CursorController.

CursorController.cls

We are keeping an instance of cursor and keep using that for each intearction from LWC. The wrapper stores the info about current position and batch size.

public with sharing class CursorController {
    
    @AuraEnabled
    public static CursorResultWrapper processCursor(CursorResultWrapper wrapper){
        try {
            Database.Cursor cursorLocator;
            if(wrapper.stringlocator == null){
                cursorLocator = Database.getCursor('SELECT Id, Name FROM Contact');
            }else{
                cursorLocator = (Database.Cursor)JSON.deserializeStrict(wrapper.stringlocator, Database.Cursor.class);
            }
            wrapper.records = cursorLocator.fetch(wrapper.position, wrapper.batchSize);
            wrapper.stringlocator = JSON.serialize(cursorLocator);
            wrapper.position++;
            return wrapper;
        } catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }

    public class CursorResultWrapper{
        @auraEnabled 
        public Integer position{get;set;}
        @auraEnabled 
        public Integer batchSize{get;set;}
        @auraEnabled
        public List<Contact> records{get;set;}
        @auraEnabled
        public string stringlocator{get;set;}
    }
}

processLargeDataset.html

Next result set button will load the contacts in order it has been queried. We are also showing the current cursor position and chunk size.

<template>
    <lightning-card title="Call Next Chunk" icon-name="utility:connected_apps">
        <div class="slds-m-around_medium">
            <lightning-button label="Next Result set" onclick={callNextChunkFromCursor}></lightning-button>
            <p class="slds-m-top_medium">current cursor position : {cursorWrapper.position}</p>
            <p class="slds-m-top_medium">cursor chunk size: {cursorWrapper.batchSize}</p>
            <p class="slds-m-top_medium">cursor results</p>
            <template lwc:if={cursorWrapper.records} for:each={cursorWrapper.records} for:item="contact">
                <p key={contact.Id}>{contact.Name}</p>
            </template>
        </div>
    </lightning-card>
</template>

processLargeDataset.js

To pass the cursor context to apex method, we have used cursorWrapper private property in js. We are component calls the apex method on load and display the result on UI.

import { LightningElement, track } from 'lwc';
import processCursor from '@salesforce/apex/CursorController.processCursor';
export default class ProcessLargeDataset extends LightningElement {

    @track cursorWrapper = {
        position : 0,
        batchSize : 2,
        records : null,
        stringlocator: null
    }

    connectedCallback(){
        this.callNextChunkFromCursor(true);        
    }

    async callNextChunkFromCursor(isloading) {
        try {
            let result = await processCursor({ wrapper: this.cursorWrapper });
            this.cursorWrapper = JSON.parse(JSON.stringify(result));
        } catch (error) {
            console.log(error);
        }
    }
}

processLargeDataset.js-meta.xml

In order to display the component on home page or record page or app page, you can set the target attribute in xml file.

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>62.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Cursor Demo

Do you need help?

Are you stuck while working on this requirement? Do you want to get review of your solution? Now, you can book dedicated 1:1 with me on Lightning Web Component completely free.

GET IN TOUCH

Schedule a 1:1 Meeting with me

Also checkout this https://salesforcediaries.com/category/lightning-web-component

Leave a Reply