-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DataGrid] Add a recipe to persist column width and order (#14560)
- Loading branch information
1 parent
ffcb087
commit 7061865
Showing
6 changed files
with
222 additions
and
0 deletions.
There are no files selected for viewing
87 changes: 87 additions & 0 deletions
87
docs/data/data-grid/column-recipes/ColumnSizingPersistWidthOrder.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import * as React from 'react'; | ||
import { | ||
DataGridPro, | ||
useGridApiRef, | ||
gridColumnFieldsSelector, | ||
} from '@mui/x-data-grid-pro'; | ||
import Button from '@mui/material/Button'; | ||
|
||
const rows = [ | ||
{ | ||
id: 1, | ||
username: '@MUI', | ||
age: 20, | ||
}, | ||
]; | ||
|
||
export default function ColumnSizingPersistWidthOrder() { | ||
const apiRef = useGridApiRef(); | ||
const [index, setIndex] = React.useState(0); | ||
const inputColumns = React.useMemo( | ||
() => [ | ||
{ field: 'id' }, | ||
{ field: 'username', width: 200, key: index }, | ||
{ field: 'age', disableReorder: true }, | ||
], | ||
[index], | ||
); | ||
|
||
const columnsState = useColumnsState(apiRef, inputColumns); | ||
|
||
return ( | ||
<div style={{ width: '100%' }}> | ||
<Button onClick={() => setIndex((prev) => prev + 1)}> | ||
Update columns reference | ||
</Button> | ||
<div style={{ height: 250 }}> | ||
<DataGridPro | ||
apiRef={apiRef} | ||
columns={columnsState.columns} | ||
onColumnWidthChange={columnsState.onColumnWidthChange} | ||
onColumnOrderChange={columnsState.onColumnOrderChange} | ||
rows={rows} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
const useColumnsState = (apiRef, columns) => { | ||
const [widths, setWidths] = React.useState({}); | ||
const [orderedFields, setOrderedFields] = React.useState(() => | ||
columns.map((column) => column.field), | ||
); | ||
|
||
const onColumnWidthChange = React.useCallback( | ||
({ colDef, width }) => { | ||
setWidths((prev) => ({ ...prev, [colDef.field]: width })); | ||
}, | ||
[setWidths], | ||
); | ||
|
||
const onColumnOrderChange = React.useCallback(() => { | ||
setOrderedFields(gridColumnFieldsSelector(apiRef)); | ||
}, [apiRef, setOrderedFields]); | ||
|
||
const computedColumns = React.useMemo( | ||
() => | ||
orderedFields.reduce((acc, field) => { | ||
const column = columns.find((col) => col.field === field); | ||
if (!column) { | ||
return acc; | ||
} | ||
if (widths[field]) { | ||
acc.push({ | ||
...column, | ||
width: widths[field], | ||
}); | ||
return acc; | ||
} | ||
acc.push(column); | ||
return acc; | ||
}, []), | ||
[columns, widths, orderedFields], | ||
); | ||
|
||
return { columns: computedColumns, onColumnWidthChange, onColumnOrderChange }; | ||
}; |
95 changes: 95 additions & 0 deletions
95
docs/data/data-grid/column-recipes/ColumnSizingPersistWidthOrder.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import * as React from 'react'; | ||
import { | ||
DataGridPro, | ||
useGridApiRef, | ||
GridColDef, | ||
GridColumnResizeParams, | ||
gridColumnFieldsSelector, | ||
GridApiPro, | ||
} from '@mui/x-data-grid-pro'; | ||
import Button from '@mui/material/Button'; | ||
|
||
const rows = [ | ||
{ | ||
id: 1, | ||
username: '@MUI', | ||
age: 20, | ||
}, | ||
]; | ||
|
||
export default function ColumnSizingPersistWidthOrder() { | ||
const apiRef = useGridApiRef(); | ||
const [index, setIndex] = React.useState(0); | ||
const inputColumns = React.useMemo( | ||
() => [ | ||
{ field: 'id' }, | ||
{ field: 'username', width: 200, key: index }, | ||
{ field: 'age', disableReorder: true }, | ||
], | ||
[index], | ||
); | ||
|
||
const columnsState = useColumnsState(apiRef, inputColumns); | ||
|
||
return ( | ||
<div style={{ width: '100%' }}> | ||
<Button onClick={() => setIndex((prev) => prev + 1)}> | ||
Update columns reference | ||
</Button> | ||
<div style={{ height: 250 }}> | ||
<DataGridPro | ||
apiRef={apiRef} | ||
columns={columnsState.columns} | ||
onColumnWidthChange={columnsState.onColumnWidthChange} | ||
onColumnOrderChange={columnsState.onColumnOrderChange} | ||
rows={rows} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
const useColumnsState = ( | ||
apiRef: React.MutableRefObject<GridApiPro>, | ||
columns: GridColDef[], | ||
) => { | ||
const [widths, setWidths] = React.useState<Record<GridColDef['field'], number>>( | ||
{}, | ||
); | ||
const [orderedFields, setOrderedFields] = React.useState<GridColDef['field'][]>( | ||
() => columns.map((column) => column.field), | ||
); | ||
|
||
const onColumnWidthChange = React.useCallback( | ||
({ colDef, width }: GridColumnResizeParams) => { | ||
setWidths((prev) => ({ ...prev, [colDef.field]: width })); | ||
}, | ||
[setWidths], | ||
); | ||
|
||
const onColumnOrderChange = React.useCallback(() => { | ||
setOrderedFields(gridColumnFieldsSelector(apiRef)); | ||
}, [apiRef, setOrderedFields]); | ||
|
||
const computedColumns = React.useMemo( | ||
() => | ||
orderedFields.reduce<GridColDef[]>((acc, field) => { | ||
const column = columns.find((col) => col.field === field); | ||
if (!column) { | ||
return acc; | ||
} | ||
if (widths[field]) { | ||
acc.push({ | ||
...column, | ||
width: widths[field], | ||
}); | ||
return acc; | ||
} | ||
acc.push(column); | ||
return acc; | ||
}, []), | ||
[columns, widths, orderedFields], | ||
); | ||
|
||
return { columns: computedColumns, onColumnWidthChange, onColumnOrderChange }; | ||
}; |
12 changes: 12 additions & 0 deletions
12
docs/data/data-grid/column-recipes/ColumnSizingPersistWidthOrder.tsx.preview
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<Button onClick={() => setIndex((prev) => prev + 1)}> | ||
Update columns reference | ||
</Button> | ||
<div style={{ height: 250 }}> | ||
<DataGridPro | ||
apiRef={apiRef} | ||
columns={columnsState.columns} | ||
onColumnWidthChange={columnsState.onColumnWidthChange} | ||
onColumnOrderChange={columnsState.onColumnOrderChange} | ||
rows={rows} | ||
/> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
--- | ||
title: Data Grid - Column recipes | ||
--- | ||
|
||
# Data Grid - Column customization recipes | ||
|
||
<p class="description">Advanced column customization recipes.</p> | ||
|
||
## Persisting column width and order | ||
|
||
When the `columns` prop reference is updated, the column width and order is reset to the `colDef.width` and the order of the `colDef` object and any updates will be lost. | ||
This is because the Data Grid considers update of the columns prop as a new set of columns, and the previous state is discarded. | ||
|
||
To persist the column width and order when the `columns` prop is updated, consider persisting the state of the columns in the userland. | ||
|
||
{{"demo": "ColumnSizingPersistWidthOrder.js", "disableAd": true, "bg": "inline"}} | ||
|
||
:::warning | ||
[Column ordering](/x/react-data-grid/column-ordering/) is a Pro feature, to use it you must be on a Pro or Premium plan. | ||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import * as React from 'react'; | ||
import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; | ||
import * as pageProps from 'docsx/data/data-grid/column-recipes/index.md?muiMarkdown'; | ||
|
||
export default function Page() { | ||
return <MarkdownDocs {...pageProps} />; | ||
} |