Skip to content

Paging and sorting

function

declare function usePagination(doc: PageableDocument, options?: PaginationOptions): Pagination;

The paging state of a query document, for a pager – the grid’s, or one an application builds.

const paging = usePagination(foos)
<button disabled={ paging.page === 0 } onClick={ () => paging.goTo(paging.page - 1) }>Previous</button>

Reads offset, page size and row count from the document and writes through update(), and holds nothing of its own. The page size is the one in the document’s config: where the type’s maxPageSize held a request to less, that is the size shown.

Parameters

doc query document snapshot; its query has to select rowCount
options page sizes to offer

interface

interface PageableDocument

What usePagination() needs of a query document. A snapshot from useInjection() or useQueryDocument() is one as long as its query selects type, config and rowCount.

type: string;
config: QueryConfig;
rowCount?: number;

optional in the type because a query need not select it, but paging needs it

update(delta: QueryConfigDelta): Promise<unknown>;

interface

interface PaginationOptions

Options for usePagination.

pageSizes?: readonly number[];

Page sizes to offer, 0 for “all rows”. Default [10, 20, 50, 100, 0].

interface

interface Pagination

The paging state of a query document, and the ways to change it.

page: number;

index of the current page, from 0

pageCount: number;

number of pages, at least 1

pageSize: number;

page size of the document’s config, 0 for all rows. What the server applied, so possibly capped.

pageSizes: number[];

Page sizes to offer: the options, held to the type’s maxPageSize, plus the current page size where it isn’t one of them, so a control always has the current size to show.

goTo(page: number): Promise<void>;

Goes to the page with the given index, held to the pages there are. Does nothing on the current page.

setPageSize(pageSize: number): Promise<void>;

Changes the page size, keeping the first row shown on the page shown. Does nothing on the current size.

function

declare function Pager({ doc, pageSizes, radius, align, className }: PagerProps): JSX.Element;

First, previous, nearby page numbers, next and last page, and a page size select, for any query document.

Built on usePagination() and nothing else, so a pager that has to look different is written the same way.

type

type PagerProps = PaginationOptions & {
/**
* Query document snapshot to page. Its query has to select `type`, `config` and `rowCount`.
*/
doc: PageableDocument;
/**
* Page numbers to list on either side of the current one. Default 2.
*/
radius?: number;
/**
* Where the pager sits in its row. Default "start".
*/
align?: "start" | "center" | "end";
/**
* Added to the pager's own classes.
*/
className?: string;
};

function

declare function pageCount(rowCount: number, pageSize: number): number;

Number of pages the rows take up. At least 1, so an empty result is one empty page and not none.

Parameters

rowCount total number of rows, as in a document’s rowCount
pageSize rows per page, 0 for all

function

declare function pageIndex(offset: number, pageSize: number): number;

Index of the page that starts at or contains the given offset.

Parameters

offset offset in rows, as in a query config
pageSize rows per page, 0 for all

function

declare function pageOffset(page: number, pageSize: number): number;

Offset of the page with the given index.

Parameters

page page index, from 0
pageSize rows per page, 0 for all

function

declare function pageSizeOptions(options: readonly number[], maxPageSize?: number): number[];

The page sizes a control can offer given the type’s maxPageSize from config().meta.

Without a limit the options come back as they are. With one, sizes above it are dropped and so is 0 (“all rows”), which the server would cap too, and the limit itself is added last in their place. What is left keeps the order it was given in.

Parameters

options page sizes to offer, 0 for “all rows”
maxPageSize the type’s largest page, absent for no limit

function

declare function pageWindow(page: number, pageCount: number, radius?: number): number[];

The page indexes a pager lists as numbers: the current page and up to radius pages on either side of it. Near either end the window shifts so it still holds 2 * radius + 1 pages where there are that many.

Parameters

page current page index, from 0
pageCount number of pages, as from pageCount()
radius pages to list on either side of the current one

function

declare function useSort(doc: SortableDocument, key: FieldExpression): SortState;

The sort state of one sort key – a column header’s, or any other control’s that sorts by one thing.

Reads the document’s config and writes it through update(), and holds nothing of its own: whatever set the sort, this shows it.

const sort = useSort(foos, "name")
<button onClick={ sort.toggle }>
Name { sort.direction === "asc" ? "▲" : sort.direction === "desc" ? "▼" : "" }
</button>

A key the sort order names itself is found first; failing that, a key taking part in an expression it sorts by.

The key is a field path ("owner.name") or a FilterDSL expression node. A key naming a direction ("!name", desc(...)) is a mistake: the direction is what toggle() changes.

Parameters

doc query document snapshot
key what to sort by

interface

interface SortableDocument

What useSort() needs of a query document: its config and update(). A snapshot from useInjection() or useQueryDocument() is one as long as its query selects config.

config: QueryConfig;
update(delta: QueryConfigDelta): Promise<unknown>;

interface

interface SortState

Where one sort key stands in a document’s sort order, and the way to sort by it.

direction: SortDirection | null;

Direction the document sorts by the key in, null if its sort order doesn’t name the key. Where the key is only part of a sort field, the direction of that expression.

position: number | null;

Index of the key in the sort order, 0 for the most significant field, null if the order doesn’t name the key. Above 0 only where something other than a header click set a sort of several fields. Keys that are part of the same expression share its index.

partial: boolean;

Whether the key is only part of the sort field it was found in, an expression like num % 10 for the key num, rather than the sort field itself. See matchSortPart().

toggle(): Promise<void>;

Sorts the document by the key alone: ascending, or descending if the document sorts by the key ascending and by nothing else. Goes back to the first page, since the rows on any other page are different ones now.

Returns the update’s promise, settled when the document holds the new rows

function

declare function SortHeader({ doc, sortKey, children, className, title }: SortHeaderProps): JSX.Element;

A table header cell that sorts the document by its key when clicked, and shows where the key stands in the document’s sort order: its direction, and its position where the order has more than one field. A key that is part of an expression the document sorts by shows the expression’s direction and position, marked qlive-grid-sorted-partial; several keys in the same expression show the same position.

Built on useSort() and nothing else, so a header that has to look different, or isn’t a table cell, is written the same way.

type

type SortHeaderProps = {
/**
* Query document snapshot to sort. Its query has to select `config`.
*/
doc: SortableDocument;
/**
* What the column sorts by: a field path or a FilterDSL expression node, without a direction.
*/
sortKey: FieldExpression;
/**
* The heading.
*/
children?: ReactNode;
/**
* Added to the header cell's own classes.
*/
className?: string;
/**
* Tooltip of the header cell, e.g. a description of the sort order the arrow and number stand for.
*/
title?: string;
};