developer guide
REST adapter
The endpoint you already have: rename its parameters, declare only the operators it truly applies, and the grid pushes what it can and finishes the rest.
For the API you already wrote
Most data does not sit behind a warehouse. It sits behind a service somebody on the team wrote, in front of a database, and until now the honest answer to "how do I connect the grid to it" was "write a fetch function". The REST adapter is that fetch function, with the query already translated into query parameters and their names yours to choose, so pointing the grid at an existing endpoint is a few lines of configuration rather than a hand-written source.
import { createGrid, createPushdownSource, restAdapter } from '@toclocoinc/lattice-grid';
import * as compute from '@toclocoinc/lattice-grid';
createGrid(el, {
columns,
rowKey: 'id',
source: createPushdownSource({
adapter: restAdapter({
url: '/api/orders',
// Rename the parameters to whatever your endpoint already calls them.
params: { offset: 'skip', limit: 'take', sort: 'orderBy', order: 'dir' },
// Declare only the comparisons the endpoint genuinely applies.
operators: ['eq', 'gt', 'lt', 'contains'],
rows: (body) => body.results, // pull the rows out of your shape
total: (body) => body.meta.totalCount, // and the match count
}),
compute,
pageSize: 100,
}),
});
Declare only what the endpoint truly does
The adapter declares almost nothing by default, and that is deliberate. Paging and sorting are assumed, because an endpoint that cannot page is not one you would put a grid in front of. Filtering is assumed absent until you say otherwise, because guessing wrong here returns the wrong rows silently rather than merely being slow. Claiming an operator the endpoint ignores would mean the grid pushes a filter that is dropped and then trusts the unfiltered result; claiming too little only costs speed. So the safe direction is to declare exactly what your endpoint genuinely applies.
restAdapter({
url: '/api/readings',
params: { offset: 'from', limit: 'size', sort: 'orderBy', order: 'dir' },
// An endpoint that pages and sorts, but does not filter:
capabilities: { sort: 'single', range: true, total: true, filter: false },
})
Whatever you do not declare, the grid does itself. Leave filtering off and the grid fetches the matching
set and filters it in the browser, correct and slower, until you widen the endpoint and the same filter
moves to the server. That trade is visible after every query through source.lastPlan(), and
the source warns once when it has to finish work the endpoint could not, naming the part.
Reading your response shape
Your endpoint returns whatever shape it already returns. Point rows at the array inside the
body and total at the match count, or pass a bare array and the adapter reads it directly.
Rename the offset, limit, sort, order, filter and search parameters with params, and encode
the filter tree however your endpoint expects with encodeFilter. Authenticate with a header
or a custom fetch.
The one thing to get right is total: it is the count of everything matching the filter, not
the length of the page returned. The grid sizes its scrollbar from it, so returning the page length
makes a large result look like a single page. If your endpoint can report the real match count, read it
into total; if it cannot, leave it and the grid manages without an exact scrollbar.
The REST adapter produces an ordinary remote source, so blocks, caching and abort-on-supersede all apply. The pushdown guide covers the capability model and the split rules in full, and connect your data lists the other options.