Implement Pagination in LWC: Step-by-Step Guide

October 27, 2025
917 Views
Implement Pagination in LWC: Step-by-Step Guide
Summarize this blog post with:

Efficient data display is crucial in Lightning Web Components, especially when you’re working with large datasets like Opportunities, Contacts, or Custom Records. Without proper pagination, loading hundreds or thousands of rows can drastically slow down performance and harm user experience.

In this guide, we will walk through what pagination is, why it matters, and a practical step-by-step method to implement pagination in Salesforce LWC with Apex — the right way.

What Is Pagination?

Pagination is the technique of splitting large data into smaller, readable chunks (pages). Instead of loading 500 records at once, you fetch 10, 20, or 50 records per page.

Page 1 → First 10 records

Page 2 → Next 10 records

Page 3 → Next 10 records

This dramatically improves performance and makes the UI more responsive.

Also Read

Don’t forget to checkout: RAG 101: What It Is and Why It Matters.

Why Do We Need Pagination in Salesforce LWC?

Benefits of Implementing Pagination in Salesforce LWC
Reason Benefit
Performance Optimization Fetches small batches → reduces server time
Better UX Easier scrolling & readability
Governor Limit Safety Avoids heap size limits
Faster Navigation Quick jumps between pages
Reusability Same logic for multiple components

Types of Pagination in Salesforce

Pagination Type Use Case Pros Cons
Offset-based (LIMIT/OFFSET) Smaller datasets (< 2000) Easy to implement Gets slower on big data
Standard Set Controller Style List views / tables Good for flexible page size More complex
Keyset / Cursor Pagination Large datasets Fast & scalable Needs custom logic

Step-by-Step Implementation Guide

Step 1: Apex Class

public with sharing class OpportunityPaginationCtrl {
			@AuraEnabled(cacheable=true)
			public static List<Opportunity> fetchOpportunities(Integer pageSize, Integer offsetValue) {
				return [
					SELECT Id, Name, StageName, Amount
					FROM Opportunity
					ORDER BY CreatedDate DESC
					LIMIT :pageSize
					OFFSET :offsetValue
				];
			}

			@AuraEnabled(cacheable=true)
			public static Integer fetchTotalCount() {
				return [SELECT COUNT() FROM Opportunity];
			}
		}
		
Step 2: LWC JavaScript

Manages pagination, tracks current page, and calls Apex.

import { LightningElement, track, wire } from 'lwc';
		import fetchOpportunities from '@salesforce/apex/OpportunityPaginationCtrl.fetchOpportunities';
		import fetchTotalCount from '@salesforce/apex/OpportunityPaginationCtrl.fetchTotalCount';

		export default class OpportunityPagination extends LightningElement {
			@track data = [];
			pageSize = 10;
			totalRecords;
			totalPages;
			currentPage = 1;

			connectedCallback() {
				fetchTotalCount().then(result => {
					this.totalRecords = result;
					this.totalPages = Math.ceil(this.totalRecords / this.pageSize);
					this.loadRecords();
				});
			}

			loadRecords() {
				let offsetValue = (this.currentPage - 1) * this.pageSize;
				fetchOpportunities({ pageSize: this.pageSize, offsetValue: offsetValue })
				.then(result => {
					this.data = result;
				});
			}

			handleNext() {
				if (this.currentPage < this.totalPages) { this.currentPage++; this.loadRecords(); } } handlePrev() { if (this.currentPage > 1) {
					this.currentPage--;
					this.loadRecords();
				}
			}
		}
		
Step 3: LWC HTML Template

<template>
			<lightning-card title="Opportunity List (With Pagination)">
				<template if:true={data}>
					<table class="slds-table slds-table_bordered">
						<thead>
							<tr>
								<th>Name</th>
								<th>Stage</th>
								<th>Amount</th>
							</tr>
						</thead>
						<tbody>
							<template for:each={data} for:item="opp">
								<tr key={opp.Id}>
									<td>{opp.Name}</td>
									<td>{opp.StageName}</td>
									<td>{opp.Amount}</td>
								</tr>
							</template>
						</tbody>
					</table>
				</template>

				<!-- Pagination Buttons -->
				<div class="slds-m-top_medium slds-align_absolute-center">
					<lightning-button label="Previous" onclick={handlePrev} disabled={currentPage === 1}></lightning-button>
					<span class="slds-m-around_medium">Page {currentPage} of {totalPages}</span>
					<lightning-button label="Next" onclick={handleNext} disabled={currentPage === totalPages}></lightning-button>
				</div>
			</lightning-card>
		</template>
		

Enhancements You Can Add

Feature Description
Search + Pagination Filter records dynamically
Inline Editing Edit rows directly inside table
Page Size Selector User can select 10/20/50 rows
Sorting Sort by amount/stage/name
Keyset Pagination Faster for > 2000 records

Best Practices

  • Always use @AuraEnabled(cacheable=true) for GET requests
  • Fetch only required fields (avoid SELECT *)
  • Avoid OFFSET for very large data → use Keyset Pagination
  • Handle empty pages (last deletion scenario)
  • Improve UX using skeleton load or spinner

Conclusion

Pagination isn’t just a UI feature — it’s a performance optimization strategy in Salesforce LWC. With the right implementation, you deliver a smoother experience for end users while staying within Salesforce governor limits.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Written by

Khumed Khatib

8x Salesforce certified || Senior Engineering Lead Salesforce at Persistent Systems || 2x Ranger || Blogger || LWC || Aura||integration

Get the latest tips, news, updates, advice, inspiration, and more….

Contributor of the month
contributor
Antonina Kharchenko

Technical Writer, Salesforce Admin at SFApps.info

...
Categories
...
Boost Your Brand's Visibility

Want to promote your products/services in front of more customers?

...

Leave a Reply

Your email address will not be published. Required fields are marked *