Lattice Grid Buy a licence

developer guide

Remote source

For datasets too large to hold: the server does the sort, filter, grouping, totals and pivot, and the grid fetches blocks on demand as the user scrolls.

The server does the work

The remote source is the mode for data too large to hold in the browser. Grouping, totals, sorting, filtering and pivoting are all delegated to the server, and the grid requests rows one group level at a time as the viewport reaches them. That is what lets a grid sit in front of a dataset of any size and stay responsive: the browser holds a few blocks, and the server answers a query over the whole set.

createGrid(el, {
  columns,
  rowKey: 'id',
  source: {
    mode: 'remote',
    pageSize: 100,
    async fetch(req) {
      // req carries the whole query, at protocol version 1:
      //   range      { start, end }        the block wanted
      //   sort       [{ col, dir }, …]     multi-column
      //   filters    the condition tree
      //   quick      free-text search
      //   groupBy    columns to group on
      //   groupPath  which group level is being expanded
      //   totals     columns to total
      //   pivotBy    columns to pivot on
      //   context    your own opaque value, passed straight through
      const res = await api.query(req, { signal: req.signal });
      return { rows: res.rows, total: res.total };   // or 'count'
    },
  },
});

The request is a published protocol

Every request your callback receives carries protocol: 1 and a documented shape, so you target the published version rather than reverse-engineering what the current release happens to send. It is not an opaque object: the filters field is the same condition tree documented across the rest of the guide, and the sort is a plain array. Beyond the range, sort and filter that the paged source also sends, the remote request adds groupBy, groupPath, pivotBy, totals and your own context, so a server that can group and aggregate does that work instead of the browser.

Grouping fetches one level at a time

When the grid is grouped, it asks the server for the top-level groups first, and for a group's children only when that group is expanded. Each expanded group owns its own block cache, so expanding one group does not invalidate its siblings, and expansion state survives a reload because it is keyed by a stable group key rather than by scroll position. Totals arrive on the group rows from the server and are used as given; the grid does not recompute a figure the server already calculated.

Blocks, caching and superseding

Blocks are fetched as the viewport reaches them and cached. Changing the sort or the filter invalidates the cache and re-queries, because the server may return an entirely different window for the same range. A request that is superseded by a newer one aborts itself through the signal on the request, so a fast scroll or a quick succession of filters does not leave stale responses racing to land. Return a total (or count, both are honoured) and the scrollbar is exact; omit it and the source discovers the length as it goes.

As with the paged source, a configured host filter is never sent and warns once, because filtering only the fetched window would give wrong results. The grid does not show a wrong answer in place of a visible one.

Or let an adapter write the query

A remote source hands you the whole request and leaves the translation to your endpoint. If your data lives behind a query engine, a pushdown adapter inverts that: you declare what the engine can answer and the grid builds the query and finishes the rest. OData, DuckDB, REST and DFQL adapters all ship, and each produces an ordinary remote source, so everything on this page applies to them unchanged.

See it running: remote, with the server doing the work. For the full set of options, start from connect your data.