Lattice Grid Buy a licence

demo D146

Pinned rows: JavaScript Data Grid Demo

A grand total pinned below the scrolling body

grandTotalRow: 'bottom'

This grid fixes a grand total row below the scrolling body so it stays visible wherever the reader has scrolled. It keeps the figure a reader is really after in view at all times, rather than at the far end of a long table.

Building…
Loading a live grid…

The configuration

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

<div id="grid" style="height: 540px"></div>

<script>
  const grid = LatticeGrid.createGrid(document.getElementById('grid'), {
    rowKey: 'id',
    selection: 'multiple',
    toolPanel: {
      side: 'left',
      panels: ['columns', 'filters', 'views', 'quick'],
      actions: ['undo', 'redo', 'export', 'restore', 'maximise'],
      exportName: 'lattice-demo',
    },
    // Pins the grand total below the scrolling body, held out of the scroll.
    grandTotalRow: 'bottom',
    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: 'region', title: 'Region', filter: { type: 'set' } },
      { 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: 'change', title: 'Change', type: 'number',
        layout: { width: 140, min: 140 }, format: { style: 'percent', decimals: 1 } },
      { field: 'cost', title: 'Monthly cost', type: 'number', layout: { width: 170 },
        format: { style: 'currency', currency: 'USD', decimals: 2 }, total: 'sum' },
    ],
    rows,  // 200,000 cloud cost rows
  });
</script>

Pinning a totals row below the scrolling body

Pinned rows fix a row, or a small set of rows, outside the scrolling body of a JavaScript data grid so it stays visible regardless of where the reader has scrolled the rest of the data. A grand total is the common case: a reader scans a few thousand line items, and the sum, average or count at the foot of the column needs to sit in view the whole time rather than requiring a scroll to the bottom to check it. Lattice Grid controls this through grandTotalRow: 'bottom', which renders an aggregated row anchored beneath the scrolling body; the same mechanism accepts 'top' to anchor the row above the body instead, ahead of the first data row. The same idea extends to a row of your own choosing rather than an aggregated total: pinnedTopRows and pinnedBottomRows pin whatever objects you pass, rendered through the ordinary column pipeline but excluded from counting, sorting, filtering and export. See the step-by-step how to pin rows to the top of a grid guide for a runnable example and the source.

The pinned row shares column widths, alignment and pinned-column regions with the scrolling body, so a total lines up under its column without separate configuration, including when that column itself is pinned to the left or right edge. It sits outside the virtualised row set, so it does not shift position as the body is scrolled, resized or filtered. For screen reader users, the pinned row keeps its place in the grid’s row and column model, so assistive technology reports it by its actual row role rather than as a detached decoration outside the data.

How do you pin a totals row to the bottom of a data grid?

Set grandTotalRow: 'bottom' in the grid configuration. Lattice Grid renders the aggregated row outside the scrolling body, anchored to the bottom edge, sharing the same column widths and pinned regions as the rows above it. Use 'top' to anchor the row above the body instead.