Remote Pagination in PrimeNG DataTable: Lazy-Loading Done Right
PrimeNG DataTable’s lazy-loading setup is straightforward once you match the `onLazyLoad` event to the right query parameters and shape your backend response correctly.
04 Jun 2026, 06:31 UTC

Problem: Remote pagination feels like magic until it doesn’t
You drop a pDataTable into a PrimeNG component tree, set rows=10, and expect the table to page data on demand. Out of the box, the component renders whatever is in its value input. To fetch data from a remote endpoint you need to turn on lazy loading, wire the onLazyLoad event, and make sure your server understands what to do with the pagination parameters PrimeNG sends. This guide assumes PrimeNG 15 or newer; earlier releases may omit certain LazyLoadEvent properties.
Activate lazy loading with rows and scrollHeight
Lazy loading in PrimeNG DataTable is opt‑in. Set the rows input to page size and scrollHeight to enable the virtual scrolling container. Then bind onLazyLoad to a handler that receives a LazyLoadEvent object.
// Minimal lazy‑load handler
@ViewChild('dt') dt: DataTable;
onLazyLoad(event: LazyLoadEvent) {
const { first, rows, sortMeta, filters } = event;
// first = index of first visible row
// rows = page size
// send first/rows to your backend as query parameters
this.dataService.fetchPage(first, rows, sortMeta, filters);
}
When rows changes, the paginator and page‑size dropdown update automatically, so users can switch pages without manual state management.
Match the backend contract
The most common stumble is a mismatch between the shape PrimeNG expects and what your API returns. PrimeNG typically expects a response object with a content array and a totalElements count, or you must map your own payload to the LazyLoadEvent fields. If the backend ignores the first and rows query parameters, the table will display incorrect totals or throw an error.
Assuming a Spring‑Data‑style endpoint, your request might look like GET /api/items?page=0&size=10. The first parameter maps to page (zero‑based) and rows to size. Your service then returns:
{
"content": [...], // array of data for the current page
"totalElements": 1234 // total row count for pagination controls
}
If your API uses different field names, adjust the mapping inside onLazyLoad before assigning event.rows and event.first.
VirtualScroll: when to combine and when to avoid
PrimeNG’s virtualScroll can render large datasets without loading every row into the DOM, but combining it with lazy loading requires care. Both components attempt to measure container dimensions, which can cause layout thrashing if they compete for the same space. A practical rule of thumb: use scrollHeight on the DataTable container and keep virtualScroll on a separate inner element, or skip virtualScroll entirely if your row count stays under a few hundred.
If you do combine them, coordinate the offsets: virtualScroll’s itemSize should align with the DataTable’s row height, and its cacheSize must account for the lazy‑loaded pages you’re fetching remotely.
Verify what you’ve built
- Open the browser devtools Network tab and confirm that every page request includes
firstandrowsas query parameters. - Inspect the console: the
onLazyLoadcallback should fire each time you paginate, and the emittedLazyLoadEventvalues should match what you’re sending to the server. - Compare the table’s
firstproperty before and after page changes; it should increment byrowseach time.
These checks confirm that the client‑server handshake is working as intended.
Closing
Remote pagination in PrimeNG DataTable becomes a reliable pattern once you treat the onLazyLoad event as the central routing point for page requests, match your backend’s response shape, and verify the parameter flow with devtools. If you’re working with under a few hundred rows, skipping lazy loading and virtualScroll altogether may be the simplest path. Otherwise, follow the checks above and you’ll have a DataTable that pages efficiently without drowning the network or the UI.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.