Lattice Grid Buy a licence

react data grid · data router

React Grid: Data Router

One feed, split across as many grids as you want by a key on each record. Push a record into the router and it lands, updates or leaves the right grid on its own; neither grid below owns its own fetch or its own WebSocket.

Also in: Angular Vue Svelte

Install and import

npm install @toclocoinc/lattice-grid
# free on localhost; a production domain needs a licence key (see /pricing/)

The files

lattice.ts

// lattice.ts
import React from 'react';
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import { createDataRouter } from '@toclocoinc/lattice-grid/modules/data-router';
import { createLatticeReact } from '@toclocoinc/lattice-grid/modules/react';

export const { LatticeGrid, useLatticeRouter, LatticeRouterProvider } =
  createLatticeReact({ React, createGrid, createDataRouter });

Orders.tsx

// Orders.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import { LatticeGrid, useLatticeRouter, LatticeRouterProvider } from './lattice';

const MONEY = { style: 'currency', currency: 'USD', decimals: 0 };
const orderColumns = [
  { field: 'id', title: 'Ref', layout: { width: 110, pin: 'start' } },
  { field: 'region', title: 'Region', filter: { type: 'set' } },
  { field: 'service', title: 'Service', filter: { type: 'set' } },
  { field: 'value', title: 'Value', type: 'number', format: MONEY, total: 'sum' },
];
const returnColumns = orderColumns.map((c) => (c.field === 'value' ? { ...c, title: 'Refund' } : c));

function Orders() {
  // Built once, in the effect useLatticeRouter runs, and destroyed with it:
  // rebuilding on every render would drop every attached grid and every row
  // it holds.
  const router = useLatticeRouter({ key: 'type', rowKey: 'id' });

  return (
    <LatticeRouterProvider router={router}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
        <LatticeGrid
          route="order"
          rowKey="id"
          selection="multiple"
          highlightOnChange={{ duration: 500 }}
          columns={orderColumns}
          rows={[]}
          style={{ height: '320px' }}
        />
        <LatticeGrid
          route="return"
          rowKey="id"
          highlightOnChange={{ duration: 500 }}
          columns={returnColumns}
          rows={[]}
          style={{ height: '320px' }}
        />
      </div>
    </LatticeRouterProvider>
  );
}

createRoot(document.getElementById('orders')!).render(<Orders />);

See it running

Building…
Loading a live grid…

Open this demo's React tab →

Working in React

The router is scoped to where you build it. useLatticeRouter creates the router in an effect and destroys it in that effect's cleanup, so it returns null on the first render; every <LatticeGrid route="…"> beneath the matching <LatticeRouterProvider> attaches to it automatically by naming a route, with no ref passed down.

The config is read once. Rebuilding the router would drop every attached grid and every row it holds, so pass a router configuration you are not going to change on every render.

A grid still needs its own columns. The router moves rows by key; it does not decide what a grid displays, so each route's grid configures its own columns exactly as a standalone grid would, as returnColumns does above by adapting orderColumns.

Related