Skip to content
module@warp-drive/experiments/pagination @experimental

Interface PaginationState<RT = unknown, E = unknown> sincev5.9.0 ​

ts
interface PaginationState<RT = unknown, E = unknown> {
  activePage: 
  | Readonly<PageCache<RT, E>>
  | null;
  adoptPage: (request: Future<RT>) => Promise<RT | null>;
  loadNext: () => Promise<RT | null>;
  loadPage: (url: string) => Promise<RT | null>;
  loadPrev: () => Promise<RT | null>;
  get activePageRequest(): Future<RT> | null;
  get data(): Iterable<ContentItem<RT>>;
  get hasNext(): boolean;
  get hasPrevious(): boolean;
  get nextRequest(): Future<RT> | null;
  get pages(): Iterable<Readonly<PageCache<RT, E>>>;
  get previousRequest(): Future<RT> | null;
  get totalPages(): number;
}

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:128

Hideconstructor

The per-component, local pagination state. It houses the state that is unique to a single component instance — the active page and navigation — while referencing a shared PaginationCache for the page graph and data.

This is the object yielded by the <Paginate /> component, narrowed by the component's @mode arg to one of its two navigation surfaces so the two APIs cannot be mixed:

Both surfaces read the same shared page graph; the mode only selects which API is exposed.

Instances are created via getPaginationState (or by the <Paginate /> component on your behalf), never constructed directly.

Type Parameters ​

RT ​

RT = unknown

E ​

E = unknown

Implements ​

Properties ​

activePage ​

ts
activePage: 
  | Readonly<PageCache<RT, E>>
  | null;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:150

The page the paged surface is currently showing. Starts at the page this component first loaded and moves whenever loadPage runs (for example a numbered link is clicked).

Implementation of ​

PagedPaginationState.activePage


adoptPage ​

ts
adoptPage: (request: Future<RT>) => Promise<RT | null>;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:539

Adopts an externally-issued request into this pagination, making its page the activePage — the programmatic entry point for route-driven navigation when managing a PaginationState directly (the <Paginate /> component uses the same mechanism for a changed @request arg).

Awaits the request and verifies that its document is a page of this state's collection (same first — or self — link). On a match, the page is loaded (a page already in the shared cache is reused) and — once its request settles — committed: it becomes the active page, and the infinite surface's run is kept coherent (a page already inside the run leaves it untouched, an adjacent page extends it, a disjoint page resets the run to the adopted page). The commit happens only after the page has loaded, so the previous page stays active — and rendered — while the adoption resolves. Returns the page's document.

Concurrent calls race safely: the latest call wins. An earlier in-flight adoption is superseded and commits nothing, and a loadPage navigation also supersedes a pending adoption (the user's click is the newer intent).

Returns null — leaving the state untouched — whenever the adoption does not commit:

  • the request (or its page's load) rejected
  • the document is a page of a different collection
  • this state has not finished setting up its own collection yet
  • the call was superseded by a newer navigation

In development, a document that contradicts the collection's page numbers (a next that skips a page, a first that is not page 1, ...) rejects instead of resolving: the graph is not updated from it.

ts
const pages = getPaginationState(initialRequest);
// later, e.g. in a route model hook reacting to a ?page= param:
const adopted = await pages.adoptPage(store.request(query));
if (adopted === null) {
  // not part of this collection — start a fresh pagination
}

It is a stable reference, so it is safe to pass around as an "action" or "event" handler.

Parameters ​

request ​

Future<RT>

Returns ​

Promise<RT | null>

Implementation of ​

PagedPaginationState.adoptPage


loadNext ​

ts
loadNext: () => Promise<RT | null>;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:611

Extends the forward frontier by one page, appending it to data. Mirror of loadPrev.

In templates it is also available as the loadNext content feature (InfinitePaginationContentFeatures.loadNext) yielded by <Paginate />; the two are the same function.

gts
<button {{on "click" pages.loadNext}}>Load more</button>

Returns ​

Promise<RT | null>

Implementation of ​

InfinitePaginationState.loadNext


loadPage ​

ts
loadPage: (url: string) => Promise<RT | null>;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:686

Loads a specific page by its URL and makes it the activePage, requesting it first if it is not already loaded. This is the paged surface's navigation entry point, called by the numbered and relational links.

In templates it is also available as the loadPage content feature (PagedPaginationContentFeatures.loadPage) yielded by <Paginate />; the two are the same function.

It is a stable reference, so it is safe to pass around as an "action" or "event" handler. Returns the page's value, or null if it has none or the load fails.

On failure the page stays active and activePageRequest resolves to it, so a wrapping <Request> renders its error block. Calling again (for example clicking the page's link a second time) retries: the failed page is re-requested with a forced reload. In development, a document that contradicts the collection's page numbers rejects instead (see adoptPage).

gts
<EachLink @pages={{pages}}>
  <:link as |link|>
    <button {{on "click" (fn features.loadPage link.url)}}>{{link.text}}</button>
  </:link>
</EachLink>

Parameters ​

url ​

string

Returns ​

Promise<RT | null>

Implementation of ​

PagedPaginationState.loadPage


loadPrev ​

ts
loadPrev: () => Promise<RT | null>;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:595

Extends the backward frontier by one page, prepending it to data. The frontier advances only once the page has loaded, so previousRequest tracks the in-flight page meanwhile. Returns the loaded value, or null when there is no previous page or the load fails.

On failure the frontier stays put and previousRequest keeps resolving to the failed page, so a wrapping <Request> renders its error block. Calling again retries: the failed page is re-requested with a forced reload.

In templates it is also available as the loadPrev content feature (InfinitePaginationContentFeatures.loadPrev) yielded by <Paginate />; the two are the same function.

It is a stable reference, so it is safe to pass around as an "action" or "event" handler.

Returns ​

Promise<RT | null>

Implementation of ​

InfinitePaginationState.loadPrev

activePageRequest ​

Get Signature ​

ts
get activePageRequest(): Future<RT> | null;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:225

The request for the activePage, for the paged surface to render. This is what a single-page view wraps in a <Request> to show the active page's loading, error, and content states:

gts
<Paginate @request={{this.request}}>
  <:content as |pages|>
    <Request @request={{pages.activePageRequest}}>
      <:content as |result|>
        {{#each result.data as |item|}}...{{/each}}
      </:content>
    </Request>
  </:content>
</Paginate>
Returns ​

Future<RT> | null

Implementation of ​

PagedPaginationState.activePageRequest


data ​

Get Signature ​

ts
get data(): Iterable<ContentItem<RT>>;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:323

The accumulated items across the loaded run, from the backward frontier to the forward frontier inclusive — the single set an infinite collection renders. Grows as loadNext/loadPrev extend the frontier. Scoped to this component's frontier (not the shared cache), so components paging the same collection to different extents each see only what they have scrolled through.

The flattened items of pages, as one contiguous iterable. For the items of every loaded page in the whole collection, see PaginationCache.data.

gts
<Paginate @request={{this.request}} @mode="infinite">
  <:content as |pages features|>
    {{#each pages.data as |item|}}...{{/each}}
    {{#if pages.hasNext}}
      <button {{on "click" features.loadNext}}>Load more</button>
    {{/if}}
  </:content>
</Paginate>
Returns ​

Iterable<ContentItem<RT>>

Implementation of ​

InfinitePaginationState.data


hasNext ​

Get Signature ​

ts
get hasNext(): boolean;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:345

Whether a page exists after the forward frontier — i.e. there is more to load going forward. Use to hide the trailing load-more sentinel at end-of-list:

gts
{{#if pages.hasNext}}
  <button {{on "click" features.loadNext}}>Load more</button>
{{/if}}
Returns ​

boolean

Implementation of ​

InfinitePaginationState.hasNext


hasPrevious ​

Get Signature ​

ts
get hasPrevious(): boolean;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:353

Whether a page exists before the backward frontier.

Returns ​

boolean

Implementation of ​

InfinitePaginationState.hasPrevious


nextRequest ​

Get Signature ​

ts
get nextRequest(): Future<RT> | null;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:376

The request for the page just after the forward frontier, for the infinite surface. null until loadNext fires it (so a <Request> wrapping it renders its idle block), the in-flight Future while that page loads, then null again once the frontier advances onto it. Also null at end-of-list, and while the page sits loaded in the shared cache (another component scrolled to it) but outside this run — loadNext then joins it without a request of its own.

gts
{{#if pages.hasNext}}
  <Request @request={{pages.nextRequest}}>
    <:idle><button {{on "click" features.loadNext}}>Load more</button></:idle>
    <:loading><Spinner /></:loading>
  </Request>
{{/if}}
Returns ​

Future<RT> | null

Implementation of ​

InfinitePaginationState.nextRequest


pages ​

Get Signature ​

ts
get pages(): Iterable<Readonly<PageCache<RT, E>>>;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:263

The pages of the run this component is viewing, from the backward frontier to the forward frontier inclusive, in order. Part of the infinite surface: it is the same run as data, yielding the PageCache objects instead of their flattened items — use it when the UI needs per-page boundaries or request states.

Grows as loadNext/loadPrev extend the frontier. Scoped to this component's frontier (not the shared cache), so components paging the same collection to different extents each see only what they have scrolled through. For every page known to the whole collection, see PaginationCache.pages.

The run is walked through the shared graph, so it ends early when a page that was in it no longer follows the page before it — a reload that showed the collection now ends sooner, or that its next cursor moved. It also ends before a page this component never loaded: a reload may relink a page in the run to one another component sharing the collection scrolled to, and that page joins this run only through loadNext.

Returns ​

Iterable<Readonly<PageCache<RT, E>>>

Implementation of ​

InfinitePaginationState.pages


previousRequest ​

Get Signature ​

ts
get previousRequest(): Future<RT> | null;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:389

The request for the page just before the backward frontier. Mirror of nextRequest for loadPrev.

Returns ​

Future<RT> | null

Implementation of ​

InfinitePaginationState.previousRequest


totalPages ​

Get Signature ​

ts
get totalPages(): number;

Defined in: warp-drive-packages/core/src/signals/pagination-state.ts:238

The total number of pages in the collection, or 0 when it is unknown (for example a cursor-based collection that reports no total).

gts
<p>Page {{pages.activePage.pageNumber}} of {{pages.totalPages}}</p>
Returns ​

number

Implementation of ​

PagedPaginationState.totalPages

Released under the MIT License.