Lattice Grid Buy a licence

demo D156

Aligned grids

A summary band whose columns stay locked to the detail grid

alignedGrids: [grid]

Building…
Loading a live grid…

The configuration

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.css">
<script src="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.js"></script>

<div id="summary" style="height: 82px"></div>
<div id="detail" style="height: 396px; margin-top: 8px"></div>

<script>
  const columns = [
    { field: 'service', title: 'Service', layout: { pin: 'start', width: 170 } },
    { field: 'team', title: 'Team', layout: { width: 150 } },
    { field: 'owner', title: 'Owner', layout: { width: 170 } },
    { field: 'region', title: 'Region', layout: { width: 150 } },
    { field: 'tier', title: 'Tier', layout: { width: 120 } },
    { field: 'instances', title: 'Instances', type: 'number', total: 'sum', layout: { width: 130 } },
    { field: 'cpuCores', title: 'vCPU', type: 'number', total: 'sum', layout: { width: 120 } },
    { field: 'memoryGb', title: 'Memory GB', type: 'number', total: 'sum', layout: { width: 150 } },
    { field: 'requests', title: 'Requests', type: 'number', total: 'sum', format: { notation: 'compact' }, layout: { width: 150 } },
    { field: 'errors', title: 'Errors', type: 'number', total: 'sum', layout: { width: 130 } },
    { field: 'p95Ms', title: 'p95 ms', type: 'number', layout: { width: 130 } },
    { field: 'monthlyCost', title: 'Monthly cost', type: 'number', total: 'sum', format: { style: 'currency', currency: 'USD' }, layout: { width: 175 } },
    { field: 'budget', title: 'Budget', type: 'number', total: 'sum', format: { style: 'currency', currency: 'USD' }, layout: { width: 160 } },
    { field: 'headcount', title: 'Headcount', type: 'number', total: 'sum', layout: { width: 150 } },
  ];

  // A one-row summary band over the same columns.
  const summary = LatticeGrid.createGrid(document.getElementById('summary'), {
    rowKey: 'id', columns, rows: totals,  // a single totals row
  });

  // The detail grid names the summary in alignedGrids: scroll it sideways and
  // the summary band tracks it, column for column.
  const detail = LatticeGrid.createGrid(document.getElementById('detail'), {
    rowKey: 'id', columns, rows,  // the service rows
    alignedGrids: [summary],
  });
</script>

Locking two grids to one column layout

Aligned grids are two separate grids whose columns stay locked to each other, so a summary band and a detail grid below it read as one table split into sections. A developer reaches for this when a header of totals or a filter row should sit above a long scrolling body but keep its own behaviour: a summary band that never scrolls out of view, a compact overview above a dense detail table, a totals strip that must stay column-for-column with the rows it summarises. Lattice Grid links them with alignedGrids: [grid], pointing each grid at the other so that resizing, reordering, or hiding a column in one is mirrored in the other and the two never drift out of alignment. As a JavaScript data grid, each grid keeps its own virtualised body, so the summary can hold a handful of rows while the detail grid holds many thousands, and only the detail body pays the cost of scrolling. Column widths propagate as measurements rather than repeated per row, so keeping the two aligned adds no per-row work, and each grid remains an independent table region for assistive technology while sharing one column structure.

How do I keep two data grids aligned to the same columns?

Set alignedGrids: [grid] on each grid, pointing it at the other. Resizing, reordering, or hiding a column in one grid is then mirrored in the other, so a summary band and a detail grid below it stay column-for-column aligned and read as one table. Each grid keeps its own rows and its own virtualised body.