Skip to content

Commit

Permalink
[docs] Add renderHeader recipe to the Master Details docs (mui#13370)
Browse files Browse the repository at this point in the history
Signed-off-by: Michel Engelen <[email protected]>
Co-authored-by: Andrew Cherniavskii <[email protected]>
Co-authored-by: Sycamore <[email protected]>
  • Loading branch information
3 people authored and thomasmoon committed Sep 6, 2024
1 parent 766c3fc commit 6e1dcd9
Show file tree
Hide file tree
Showing 6 changed files with 322 additions and 0 deletions.
26 changes: 26 additions & 0 deletions docs/data/data-grid/master-detail/master-detail.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,31 @@ This approach can also be used to change the location of the toggle column, as s
As any ordinary cell renderer, the `value` prop is also available, and it corresponds to the state of the row: `true` when expanded and `false` when collapsed.
:::

## Custom header for detail panel column

To render a custom header for the detail panel column, use the [`renderHeader`](/x/react-data-grid/column-header/#custom-header-renderer) property in the column definition.
This property receives a `GridRenderHeaderParams` object that contains `colDef` (the column definition) and `field`.
The following example demonstrates how to render a custom header for the detail panel column:

```tsx
const columns = [
{
...GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
renderHeader: (params) => (
<div>
<span>{params.colDef.headerName}</span>
<button onClick={() => console.log('Custom action')}>Custom action</button>
</div>
),
},
//... other columns
];
```

:::info
For a more advanced example check out the [Expand or collapse all detail panels](/x/react-data-grid/row-recipes/#expand-or-collapse-all-detail-panels) recipe.
:::

## Disable detail panel content scroll

By default, the detail panel has a width that is the sum of the widths of all columns.
Expand All @@ -153,6 +178,7 @@ Notice that the toggle column is pinned to make sure that it will always be visi
More examples of how to customize the detail panel:

- [One expanded detail panel at a time](/x/react-data-grid/row-recipes/#one-expanded-detail-panel-at-a-time)
- [Expand or collapse all detail panels](/x/react-data-grid/row-recipes/#expand-or-collapse-all-detail-panels)

## apiRef

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<DataGridPro
rows={rows}
columns={columns}
getDetailPanelContent={getDetailPanelContent}
getDetailPanelHeight={getDetailPanelHeight}
/>
134 changes: 134 additions & 0 deletions docs/data/data-grid/row-recipes/DetailPanelExpandCollapseAll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
import {
DataGridPro,
useGridApiContext,
useGridSelector,
gridRowsLookupSelector,
gridDetailPanelExpandedRowIdsSelector,
gridDetailPanelExpandedRowsContentCacheSelector,
GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
} from '@mui/x-data-grid-pro';
import {
randomCreatedDate,
randomCurrency,
randomEmail,
randomPrice,
} from '@mui/x-data-grid-generator';

export default function DetailPanelExpandCollapseAll() {
const getDetailPanelContent = React.useCallback(
({ row }) => <Box sx={{ p: 2 }}>{`Order #${row.id}`}</Box>,
[],
);

const getDetailPanelHeight = React.useCallback(() => 50, []);

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
rows={rows}
columns={columns}
getDetailPanelContent={getDetailPanelContent}
getDetailPanelHeight={getDetailPanelHeight}
/>
</div>
);
}

function CustomDetailPanelHeader() {
const apiRef = useGridApiContext();

const expandedRowIds = useGridSelector(
apiRef,
gridDetailPanelExpandedRowIdsSelector,
);
const rowsWithDetailPanels = useGridSelector(
apiRef,
gridDetailPanelExpandedRowsContentCacheSelector,
);

const noDetailPanelsOpen = expandedRowIds.length === 0;

const expandOrCollapseAll = () => {
const dataRowIdToModelLookup = gridRowsLookupSelector(apiRef);
const allRowIdsWithDetailPanels = Object.keys(rowsWithDetailPanels).map((key) =>
apiRef.current.getRowId(dataRowIdToModelLookup[key]),
);

apiRef.current.setExpandedDetailPanels(
noDetailPanelsOpen ? allRowIdsWithDetailPanels : [],
);
};

const Icon = noDetailPanelsOpen ? UnfoldMoreIcon : UnfoldLessIcon;

return (
<IconButton
size="small"
tabIndex={-1}
onClick={expandOrCollapseAll}
aria-label={noDetailPanelsOpen ? 'Expand All' : 'Collapse All'}
>
<Icon fontSize="inherit" />
</IconButton>
);
}

const columns = [
{
...GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
renderHeader: () => <CustomDetailPanelHeader />,
},
{ field: 'id', headerName: 'Order ID' },
{ field: 'customer', headerName: 'Customer', width: 200 },
{ field: 'date', type: 'date', headerName: 'Placed at' },
{ field: 'currency', headerName: 'Currency' },
{ field: 'total', type: 'number', headerName: 'Total' },
];

const rows = [
{
id: 1,
customer: 'Matheus',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 2,
customer: 'Olivier',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 3,
customer: 'Flavien',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 4,
customer: 'Danail',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 5,
customer: 'Alexandre',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
];
138 changes: 138 additions & 0 deletions docs/data/data-grid/row-recipes/DetailPanelExpandCollapseAll.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
import {
DataGridPro,
GridColDef,
GridRowsProp,
GridRowParams,
useGridApiContext,
useGridSelector,
gridRowsLookupSelector,
gridDetailPanelExpandedRowIdsSelector,
gridDetailPanelExpandedRowsContentCacheSelector,
GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
GridRowId,
} from '@mui/x-data-grid-pro';
import {
randomCreatedDate,
randomCurrency,
randomEmail,
randomPrice,
} from '@mui/x-data-grid-generator';

export default function DetailPanelExpandCollapseAll() {
const getDetailPanelContent = React.useCallback(
({ row }: GridRowParams) => <Box sx={{ p: 2 }}>{`Order #${row.id}`}</Box>,
[],
);

const getDetailPanelHeight = React.useCallback(() => 50, []);

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
rows={rows}
columns={columns}
getDetailPanelContent={getDetailPanelContent}
getDetailPanelHeight={getDetailPanelHeight}
/>
</div>
);
}

function CustomDetailPanelHeader() {
const apiRef = useGridApiContext();

const expandedRowIds = useGridSelector(
apiRef,
gridDetailPanelExpandedRowIdsSelector,
);
const rowsWithDetailPanels = useGridSelector(
apiRef,
gridDetailPanelExpandedRowsContentCacheSelector,
);

const noDetailPanelsOpen = expandedRowIds.length === 0;

const expandOrCollapseAll = () => {
const dataRowIdToModelLookup = gridRowsLookupSelector(apiRef);
const allRowIdsWithDetailPanels: GridRowId[] = Object.keys(
rowsWithDetailPanels,
).map((key) => apiRef.current.getRowId(dataRowIdToModelLookup[key]));

apiRef.current.setExpandedDetailPanels(
noDetailPanelsOpen ? allRowIdsWithDetailPanels : [],
);
};

const Icon = noDetailPanelsOpen ? UnfoldMoreIcon : UnfoldLessIcon;

return (
<IconButton
size="small"
tabIndex={-1}
onClick={expandOrCollapseAll}
aria-label={noDetailPanelsOpen ? 'Expand All' : 'Collapse All'}
>
<Icon fontSize="inherit" />
</IconButton>
);
}

const columns: GridColDef[] = [
{
...GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
renderHeader: () => <CustomDetailPanelHeader />,
},
{ field: 'id', headerName: 'Order ID' },
{ field: 'customer', headerName: 'Customer', width: 200 },
{ field: 'date', type: 'date', headerName: 'Placed at' },
{ field: 'currency', headerName: 'Currency' },
{ field: 'total', type: 'number', headerName: 'Total' },
];

const rows: GridRowsProp = [
{
id: 1,
customer: 'Matheus',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 2,
customer: 'Olivier',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 3,
customer: 'Flavien',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 4,
customer: 'Danail',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 5,
customer: 'Alexandre',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<DataGridPro
rows={rows}
columns={columns}
getDetailPanelContent={getDetailPanelContent}
getDetailPanelHeight={getDetailPanelHeight}
/>
12 changes: 12 additions & 0 deletions docs/data/data-grid/row-recipes/row-recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,15 @@ By default, the [Master detail <span class="plan-pro" />](/x/react-data-grid/mas
However, you can [control the expanded detail panels](/x/react-data-grid/master-detail/#controlling-expanded-detail-panels) to have only one detail panel expanded at a time.

{{"demo": "DetailPanelOneExpandedRow.js", "bg": "inline", "defaultCodeOpen": false}}

## Expand or collapse all detail panels

The following demo shows how to create a custom header element that expands or collapses all detail panels at once.

Here's how it works:

The custom header uses `gridRowsLookupSelector` to find all rows with a detail panel.
It checks the status of open panels using the [`useGridSelector` hook](/x/react-data-grid/state/#with-usegridselector) to access the grid's state.
When clicked, it uses [`setExpandedDetailPanels`](/x/api/data-grid/grid-api/#grid-api-prop-setExpandedDetailPanels) from the [Grid API](/x/react-data-grid/api-object/#how-to-use-the-api-object) to expand or collapse all detail panels.

{{"demo": "DetailPanelExpandCollapseAll.js", "bg": "inline", "defaultCodeOpen": false}}

0 comments on commit 6e1dcd9

Please sign in to comment.