demo D78
Master-detail
A row expanding into a nested grid, several open at once
detail: { rows, config }
The configuration
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.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.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.esm.min.js';
import createLatticeGrid from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/modules/react.esm.min.js';
const LatticeGrid = createLatticeGrid({ React, createGrid });
// Expanding a circuit opens a nested grid of its ports. rows reads the child
// records off the master row; the nested grid takes its own columns and row
// key. Any number of details can be open at once.
const detail = {
rows: (row) => row.data.ports,
height: 260,
// Bounds what is kept after closing, not how many may be open.
cacheLimit: 10,
config: {
rowKey: 'port',
columns: [
{ field: 'port', title: 'Port', layout: { width: 140 } },
{ field: 'vlan', title: 'VLAN', type: 'number', layout: { width: 100 } },
{ field: 'speed', title: 'Speed', type: 'number', format: { suffix: ' Gb' }, layout: { width: 110 } },
{
field: 'state', title: 'State', layout: { width: 130 },
cell: { decoration: 'dot', variant: { map: { up: 'success', down: 'danger', 'admin down': 'neutral' } } },
},
{ field: 'peer', title: 'Peer AS' },
],
},
};
const columns = [
{ field: 'circuit', title: 'Circuit', layout: { width: 160 } },
{ field: 'customer', title: 'Customer', filter: { type: 'set' } },
{ field: 'region', title: 'Region', filter: { type: 'set' } },
{
field: 'status', title: 'Status', filter: { type: 'set' }, layout: { width: 140 },
cell: { decoration: 'pill', variant: { map: { live: 'success', provisioning: 'info', ceased: 'neutral' } } },
},
{ field: 'portCount', title: 'Ports', type: 'number', layout: { width: 100 } },
{ field: 'charge', title: 'Monthly charge', type: 'number',
format: { style: 'currency', currency: 'GBP', decimals: 0 }, total: 'sum', layout: { width: 180 } },
];
const rows = [/* circuits, each carrying its own ports array */];
function App() {
return (
<LatticeGrid
rowKey="id"
selection="multiple"
detail={detail}
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>
Nesting a grid inside a row with master-detail
Master-detail expands a row into its own grid rather than a flat sub-list: an order row opens onto its line items, a shipment row onto its parcels, each with its own columns, sorting and totals. A developer reaches for it when the child records do not fit as extra columns on the parent and are too structured for a plain text summary, and when several of those child grids might need to stay open at once for comparison. Lattice Grid controls this per row through the detail: { rows, config } option, passing the child rows and a full grid configuration for the detail, so the nested grid is not a cut-down preview but a complete instance with its own column definitions. Because this is a JavaScript data grid built on incremental rendering, opening a detail row inserts only that row’s grid into the layout rather than recalculating the rows around it, so several master rows can sit expanded together without the outer grid’s scroll position or row heights being recomputed from scratch. The detail area also participates in keyboard navigation, so focus moves from a master row into its expanded grid and back out again without a pointer.
How do I show a nested grid when a row is expanded?
Set detail: { rows, config } on the row: rows supplies the child records and config is a standard grid configuration describing their columns. Lattice Grid renders that configuration inside the expanded row as an independent grid, and any number of master rows can be expanded at the same time, each keeping its own detail state.