demo D96
Paged
A page at a time from a server that paginates
source: { mode: 'paged' }
The configuration
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.css">
<script src="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.js"></script>
<div id="grid" style="height: 540px"></div>
<script>
const grid = LatticeGrid.createGrid(document.getElementById('grid'), {
rowKey: 'id',
// This server answers a flat query only, so the columns say they cannot be
// grouped or pivoted rather than offering a control that returns nothing.
columnDefaults: { allowGroup: false, allowPivot: false },
selection: 'multiple',
toolPanel: {
side: 'left',
panels: ['columns', 'filters', 'views', 'quick'],
actions: ['undo', 'redo', 'export', 'restore', 'maximise'],
exportName: 'lattice-demo',
},
statusBar: { panels: ['rowCount', 'progress', 'updates', 'selectedCount'] },
// A page at a time, twelve pages kept. Scroll far enough and the pages
// behind you are evicted and refetched when you come back, which is the
// trade a paged source makes for never holding the dataset.
source: {
mode: 'paged',
pageSize: 100,
maxCachedPages: 12,
// Your endpoint. It is handed the range, sort and filter, and returns
// { rows, total }: the slice for the range, and the size of the full
// result set so the scrollbar knows how far it runs.
fetch: async (req) => {
const res = await fetch('/api/instruments', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(req),
signal: req.signal,
});
return res.json(); // { rows, total }
},
},
columns: [
{ field: 'symbol', title: 'Symbol', layout: { width: 130, pin: 'start' } },
{ field: 'name', title: 'Instrument', layout: { flex: 1, min: 170, max: 280 } },
{ field: 'desk', title: 'Desk', filter: { type: 'set' } },
{ field: 'region', title: 'Region', filter: { type: 'set' } },
{ field: 'price', title: 'Price', type: 'number', layout: { width: 120 },
format: { decimals: 4 }, filter: { type: 'number' } },
{ field: 'change', title: 'Change', type: 'number', layout: { width: 110 },
format: { style: 'percent', decimals: 2 } },
{ field: 'volume', title: 'Volume', type: 'number', layout: { width: 120 },
format: { notation: 'compact' }, filter: { type: 'number' } },
{ field: 'status', title: 'Status', filter: { type: 'set' }, layout: { width: 110 },
cell: { decoration: 'pill', variant: { map: { open: 'success', halted: 'danger', settled: 'neutral' } } } },
],
// No rows: under a paged source every row on screen came back from a fetch.
});
</script>
Fetching rows page by page from a server that paginates
A paged source asks the server for one page of rows at a time rather than the whole dataset or an open-ended stream, fitting any backend already built around LIMIT/OFFSET or a cursor parameter, with no response returning more than a fixed page size. A developer reaches for this when the row count is too large to hand to a JavaScript data grid in one request, but the server lacks the finer-grained querying a full server-side row model expects, such as pushing sort or filter state down per call. Lattice Grid switches the source into this pattern with source: { mode: 'paged' }, which requests bounded pages on demand as scrolling nears the edge of what it already holds, rather than fetching everything up front or streaming rows unprompted. Fetched pages are cached by index, so scrolling back to a page already retrieved renders from cache instead of issuing the request again. Rows still virtualise in the DOM as an in-memory dataset does: only the visible band plus a small overscan gets real row elements at any one time, so page size and viewport height govern memory use rather than total row count. A pending page renders its row band as a placeholder rather than blank space, keeping the row that holds focus in the layout while its data resolves.
How do I load a large dataset into a data grid without fetching it all at once?
Set source: { mode: 'paged' } and supply a function that returns one page of rows for a given page index. Lattice Grid requests pages as the visible scroll position approaches their range, caches each page once fetched, and virtualises rendering so only the current viewport’s rows exist in the DOM at any time.