Lattice Grid Buy a licence

developer guide

Using Lattice Grid with React

A thin adapter over the same grid every other page runs. You hand it React and createGrid; it hands you a component.

Install

The grid and its adapters are one package. The adapter is a separate entry point, so a bundle that never imports it never carries it.

npm i @toclocoinc/lattice-grid

The adapter is a factory

There is no component to import. You call createLatticeGrid and pass it your copy of React and the grid's createGrid, and it returns a component bound to them.

import React from 'react';
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import { createLatticeGrid } from '@toclocoinc/lattice-grid/modules/react';

// Build the component once, at module scope, not on every render.
const LatticeGrid = createLatticeGrid({ React, createGrid });

This looks like a hoop, and it is the point. The adapter takes no dependency on React and carries no second copy of the grid: both are passed in, so there is exactly one React and one grid on the page, the versions you installed, and the adapter cannot drift out of step with either. It is a few hundred bytes of glue rather than a bundled framework. Build the component once at module scope; calling the factory on every render would rebuild it each time.

Props flow through the public API

The props are the grid's own configuration. Change rows or columns and the adapter pushes the change through the grid's public API rather than tearing the grid down and rebuilding it, so scroll position, selection and open editors survive a re-render. Events the grid emits arrive as on* callbacks.

function Circuits({ rows }) {
  const columns = [
    { field: 'circuit', title: 'Circuit', layout: { pin: 'start', width: 190 } },
    { field: 'region', title: 'Region', filter: { type: 'set' } },
    { field: 'charge', title: 'Monthly charge', type: 'number',
      format: { style: 'currency', currency: 'GBP' }, total: 'sum' },
  ];

  return (
    <LatticeGrid
      rowKey="id"
      columns={columns}
      rows={rows}
      style={{ height: 520 }}
      onCellChanged={(e) => console.log('changed', e)}
    />
  );
}

Reaching the grid instance

For anything the props do not cover, an export, a programmatic filter, a scroll, the component forwards a ref whose .grid is the real instance. That is the same object the docs describe everywhere else; the adapter adds nothing to it and hides nothing from it.

const gridRef = React.useRef(null);

// gridRef.current.grid is the real grid instance: the whole public API.
<LatticeGrid ref={gridRef} rowKey="id" columns={columns} rows={rows} />;

// later, from a button or an effect:
gridRef.current.grid.export.csv({ download: true });

Cleanup on unmount

The adapter destroys the underlying grid when the component unmounts, releasing its listeners and observers, so there is nothing to clean up by hand. Unmount the component and the grid goes with it.

TypeScript

Type declarations travel with the package, so column and config types are picked up without any tsconfig work. Type your columns and the editor checks them against the grid's own definitions.

import type { GridColumn } from '@toclocoinc/lattice-grid';

const columns: GridColumn[] = [
  { field: 'charge', title: 'Charge', type: 'number', total: 'sum' },
];

One grid per page

Use the React adapter or the web component, not both on one page. The web component bundle carries its own copy of the grid, and two copies keep separate registries: a renderer registered through one is invisible to the other. Pick one entry point per page and stay on it.

See also the React data grid overview, and the rest of the developer guide.