Pagination
Reading a page
Section titled “Reading a page”Generate the URI, fetch it yourself, then hand the raw body to a Paginator. What comes back is a
PaginatedCollection — rows plus the page metadata the backend reported.
const body = await fetch(`https://example.com/api${uri}`).then((r) => r.json());const page = paginator.paginate(body);
page.data; // rowspage.total; // 57page.lastPage; // 6page.from; // 26page.to; // 50Paginator also writes that metadata back into the store, which is what lets the builder answer
questions about where you are.
Header-based pagination
Section titled “Header-based pagination”Some backends page over headers rather than the body — PostgREST’s Content-Range, WordPress’s
X-WP-TotalPages. Pass the headers as the second argument:
const response = await fetch(url);const page = paginator.paginate(await response.json(), response.headers);Anything with a .get() accessor works — the DOM Headers, Angular’s HttpHeaders — as does a
plain object. The core imports none of them.
Drivers that need to send pagination headers expose them through paginationHeaders(), which
returns null when the active driver has nothing to add, so it is safe to spread unconditionally:
await fetch(url, { headers: { ...qb.paginationHeaders() } });Moving between pages
Section titled “Moving between pages”Every navigator returns this, so a move and a regenerate is one chain:
const nextUri = qb.nextPage().generateUri();Out-of-range moves are clamped, not thrown — nextPage() on the last page is a no-op.
Syncing
Section titled “Syncing”Until a response has been parsed, the builder does not know how many pages exist. Rather than guess, it throws:
qb.totalPages();// PaginationNotSyncedError: Cannot read totalPages: no paginated response has been synced yet.Paginator.paginate() fixes that for you. If you parse responses yourself, sync manually:
store.syncLastPage(page.lastPage);Normalising rows
Section titled “Normalising rows”PaginatedCollection.normalize() reduces a page to identifiers, keyed by page number — useful when
rows live in a normalised store:
page.normalize(); // { 2: [7, 9] }page.normalize('slug'); // { 2: ['first', 'second'] }page.normalize((row) => `row-${row.id}`); // { 2: ['row-7', 'row-9'] }