Master-Detail (Enterprise)
Master-detail in apex-grid-enterprise renders a nested grid of related rows beneath each expanded master row. Setting the masterDetail config wires up the grid's row expansion automatically (creating, caching, and populating the child grids), so you don't hand-write a detailTemplate.
Basic setup
import 'apex-grid-enterprise/define';
const grid = document.createElement('apex-grid-enterprise');
grid.columns = orderColumns;
grid.data = orders;
grid.masterDetail = {
columns: [
{ key: 'sku', headerText: 'SKU' },
{ key: 'qty', headerText: 'Qty' },
{ key: 'price', headerText: 'Price' },
],
getDetailData: (order) => order.lineItems,
};
document.body.appendChild(grid);
Each expanded order row now shows a nested grid of its line items.
MasterDetailConfig
| Field | Type | Description |
|---|---|---|
columns | ColumnConfiguration[] or (row) => ColumnConfiguration[] | Detail-grid columns; a function lets each master row have its own columns |
getDetailData | (row) => C[] | Promise<C[]> | Returns the detail rows for a master row; may be async |
detailTag | 'apex-grid' | 'apex-grid-enterprise' | Which element to render the detail grid as (default 'apex-grid') |
detailHeight | number | string | Height of the detail region |
isExpandable | (row) => boolean | Whether a given master row can expand |
configureDetail | (grid, context) => void | Hook to configure each detail grid instance after creation |
Async detail data
getDetailData can return a promise, so detail rows can be fetched on demand when a master row expands:
grid.masterDetail = {
columns: lineItemColumns,
getDetailData: async (order) => {
const res = await fetch(`/api/orders/${order.id}/items`);
return res.json();
},
detailHeight: 240,
};
Per-row expandability
Use isExpandable to hide the expander on rows with no detail:
grid.masterDetail = {
columns: lineItemColumns,
getDetailData: (order) => order.lineItems,
isExpandable: (order) => order.lineItemCount > 0,
};
Enterprise detail grids
Set detailTag: 'apex-grid-enterprise' to make each detail grid itself an enterprise grid (so detail grids can group, aggregate, etc.). Use configureDetail to set up each instance:
grid.masterDetail = {
columns: lineItemColumns,
getDetailData: (order) => order.lineItems,
detailTag: 'apex-grid-enterprise',
configureDetail: (detailGrid, context) => {
detailGrid.aggregations = { price: ['sum'] };
},
};
The configureDetail context provides the master data (the row) and its rowIndex.
Refreshing a detail
When the underlying detail data changes, invalidate a single master row's cached detail:
grid.refreshDetail(order);
Turning it off
Set masterDetail back to null to turn master-detail off: rows stop being expandable and the expansion config the grid had before is restored, unless the app set a new one in the meantime (from 0.8). A getDetailData that rejects or throws shows an empty detail and asks again the next time that detail is shown.
Events from nested grids
A detail grid renders inside one of the master grid's rows, so its events cross the master's body on their way out. From 3.6 the master ignores them: clicks, Space selection, Ctrl+Z and pointer drags in a nested grid no longer drive the outer one. Your own listeners on the master can make the same check with ownsEvent:
grid.addEventListener('click', (event) => {
if (!grid.ownsEvent(event)) return // came from a detail grid
// ...
});
Relationship to manual expansion
masterDetail configures the grid's expansion automatically and overrides any manual expansion/detailTemplate you set. For fully custom expansion content without nested grids, use the community row expansion feature instead.
React example
import { useEffect, useRef } from 'react'
import 'apex-grid-enterprise/define'
export default function MasterDetailGrid() {
const ref = useRef<any>(null)
useEffect(() => {
const grid = ref.current
grid.columns = orderColumns
grid.data = orders
grid.masterDetail = {
columns: lineItemColumns,
getDetailData: (order: any) => order.lineItems,
detailHeight: 220,
}
}, [])
return <apex-grid-enterprise ref={ref} style={{ height: 520 }} />
}