Client‑Side vs Lazy Pagination in PrimeNG p‑Table: When to Choose Which
PrimeNG’s p‑Table can paginate data in‑browser or ask the server for each page via onLazyLoad. This post explains the decision factors, shows a minimal lazy‑loading example, lists pitfalls, and gives an actionable checklist.
03 Sept 2025, 04:23 UTC

Problem: Which pagination mode should you pick?
PrimeNG’s p-table can either slice the data in the browser or ask the server for each page using the onLazyLoad callback. Choosing the wrong mode can lead to unnecessary network traffic, high memory usage, or a pager that shows only one page.
Decision Factors
Use client‑side pagination when the entire data set is small enough to download once and when you want instant, in‑browser sorting and filtering. The component handles slicing, sorting and filtering automatically; you only bind the full array to value.
Use lazy (server‑driven) pagination when the data set is large, expensive to fetch, or already sorted/filtered on the backend. In this mode the table emits onLazyLoad events that contain the zero‑based offset, page size, and any sort or filter metadata; the server must return the requested slice and the total record count.
Worked Example – Lazy Table
The following Angular component demonstrates a minimal lazy‑loading table. Replace the mock fetchUsers with a real HTTP call.
// user-table.component.ts
import { Component } from '@angular/core';
import { LazyLoadEvent } from 'primeng/api';
@Component({
selector: 'app-user-table',
templateUrl: './user-table.component.html'
})
export class UserTableComponent {
users: any[] = []; // slice returned by the API
totalRecords = 0; // total rows in the full data set
loading = false; // optional spinner flag
onLazyLoad(event: LazyLoadEvent) {
this.loading = true;
// Log the event to discover its exact shape for your PrimeNG version
console.log('LazyLoadEvent', event);
const { first, rows, sortField, sortOrder, filters } = event;
const params = {
offset: first,
limit: rows,
sortField,
sortOrder,
filters
};
this.fetchUsers(params).then(resp => {
this.users = resp.items;
this.totalRecords = resp.total; // must be set after each request
this.loading = false;
});
}
// Mock API – replace with HttpClient logic
async fetchUsers(params: any) {
return new Promise(resolve => {
setTimeout(() => {
const items = Array.from({ length: params.limit }, (_, i) => ({
id: params.offset + i + 1,
name: `User ${params.offset + i + 1}`
}));
resolve({ items, total: 5000 });
}, 300);
});
}
}
// user-table.component.html
ID
Name
{{ rowData.id }}
{{ rowData.name }}
No records found
Common Pitfalls
- Missing
totalRecords: If you do not assign the total count returned by the API, the paginator will display only a single page. - Assuming
lazyLoadOnInitis always true: The default value can differ between PrimeNG major releases. Verify the default in the documentation for your installed version. - Uncertain
filtersshape: Thefiltersobject may vary; log theonLazyLoadevent to inspect its structure. - Server‑side sorting/filtering not implemented: In lazy mode the table does not apply sorting or filtering; you must forward
sortField,sortOrderandfiltersto your backend. - Page index after filter change: When filters change, the current
firstindex may point beyond the new result set. Reset the page to the first page (e.g., setfirst = 0or callpaginator.reset()if the method is exposed).
Trade‑offs & Limitations
| Aspect | Client‑side | Lazy (server‑driven) |
|---|---|---|
| Data size suitability | Small‑to‑medium (fits in memory) | Large or expensive to load fully |
| Sorting/filtering | Automatic, in‑browser | Requires backend logic |
| Network traffic | One request (full data) | Multiple requests (page‑by‑page) |
| Memory usage | All rows stored in browser | Only current slice stored |
| Implementation effort | Minimal (bind value) | Handle onLazyLoad and update totalRecords |
Actionable Checklist
- Run
npm list primengto find your installed major version. Check thelazyLoadOnInitdefault andonLazyLoadpayload shape in that version’s docs. - Estimate the total number of rows. If it is modest (≈ 5 000 rows) and users need instant sort/filter, start with client‑side pagination.
- If the data set is large, costly to load, or already sorted/filtered on the server, enable
lazy="true"and implementonLazyLoadas shown. - After each API call, assign the returned total to
totalRecords. - When filters change, reset the page index to zero or use the paginator’s reset method if available.
- Open the browser’s network tab and verify that the first request matches the chosen mode (single large payload for client‑side, small paged requests for lazy).
- Monitor memory usage in the browser dev tools to confirm that only the current slice is kept when using lazy mode.
Following this checklist will help you pick the right pagination strategy for PrimeNG’s p-table and avoid the most common configuration mistakes.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.