Lattice Grid Buy a licence

demo D66

The grand total row in React

Inline at the end, or pinned above the status bar

grandTotalRow: 'bottom'

This grid shows a single summary line for the entire dataset, either inline at the end or pinned above the status bar. It puts the one figure most reports are really after where a reader can always see it, whatever they have scrolled to.

Building…
Loading a live grid…

This is the React version. The grid mounts through the createLatticeGrid adapter, which takes its configuration as ordinary props and hands back the live grid through a ref. The grid below is the same one every other tab runs.

The configuration

<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.min.css">

<div id="grid"></div>

<script type="module">
  import React from 'https://esm.sh/react@18';
  import { createRoot } from 'https://esm.sh/react-dom@18/client';
  import { createGrid } from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/lattice-grid.esm.min.js';
  import createLatticeGrid from 'https://cdn.latticegrid.dev/lattice-grid@1.107.0/modules/react.esm.min.js';

  const LatticeGrid = createLatticeGrid({ React, createGrid });

  const columns = [
    { field: 'account', title: 'Account', filter: { type: 'set' } },
    { field: 'service', title: 'Service', filter: { type: 'set' } },
    { field: 'resource', title: 'Resource', layout: { flex: 1, min: 200, max: 320 } },
    { field: 'environment', title: 'Env', filter: { type: 'set' },
      cell: { decoration: 'pill', variant: { map: {
        prod: 'danger', 'prod-2': 'danger', 'definitely-prod': 'danger',
        staging: 'warning', untagged: 'warning', test: 'info',
        dev: 'success', 'not-prod': 'neutral',
      } } } },
    { field: 'cost', title: 'Monthly cost', type: 'number', layout: { width: 170 },
      format: { style: 'currency', currency: 'USD', decimals: 2 }, total: 'sum' },
  ];

  const rows = [/* cloud cost rows, one object per resource */];

  function App() {
    // grandTotalRow pins one summary line below the sheet, carrying the total of
    // every column that declares one, and it follows the filter as the reader
    // narrows the rows.
    return (
      <LatticeGrid
        rowKey="id"
        selection="multiple"
        grandTotalRow="bottom"
        toolPanel={{ side: 'left', panels: ['columns', 'filters', 'views', 'quick'],
          actions: ['undo', 'redo', 'export', 'restore', 'maximise'], exportName: 'lattice-demo' }}
        columns={columns}
        rows={rows}
        style={{ height: '540px' }}
      />
    );
  }

  createRoot(document.getElementById('grid')).render(<App />);
</script>

Placing a grand total row across the whole dataset

A grand total row is the single summary line that closes the entire grid rather than one group within it, distinct from a group footer, which only reduces the rows inside its own section. A developer reaches for it whenever the figure at the bottom needs to represent every row currently in the grid, such as a total revenue line under a sales sheet, regardless of how many groups sit above it. Lattice Grid controls placement with grandTotalRow: 'bottom', which docks the row inline after the last row in the JavaScript data grid; setting it to 'top' instead pins the row above the scrolling body, ahead of the header, so it stays in view above a long list rather than requiring a scroll to the foot. The row draws on the same aggregation already declared per column, so a total: 'sum' on a currency column produces a grand total in the same format as the group subtotals above it, with no separate calculation to maintain. Because the row is a synthesised row type rather than a rendered footer element, it participates in the grid’s row virtualisation, so it costs nothing extra to keep on screen at a million rows, and it carries its own aria-rowindex so a screen reader can distinguish it from an ordinary data row.

How do I add a grand total row that stays visible while scrolling?

Set grandTotalRow: 'top' rather than 'bottom'. Lattice Grid then pins the row above the scrolling body of the JavaScript data grid, ahead of the header, so the total remains on screen regardless of scroll position. The row still draws its figures from each column’s existing aggregation, so no calculation needs to be written twice.