Reputation: 21
We are using MUI DataGrid in our React based project.
At the moment I am trying to save/persist state of columns after toggling visibility of some columns with DataGrid's toolbar column menu, as currently after re-render it is back to default column setup.
I would like to know how could I access state of DataGrid/visibility state of columns in DataGrid so I can adjust/save it/reuse it later?
So far I meddled a bit with a apiRef, but all I got from apiRef.current was empty object. I am adding below some basic codeSandbox example to show how I tried to access it.
https://codesandbox.io/s/datagridprodemo-material-demo-forked-189j9?file=/demo.js
Maybe there is better/different approach, or I just need to create the state somehow. We would like to persist the state of the columns as user preference possibly in a future so this is vital for that to happen.
All suggestions are welcome and I thank you beforehand.
Upvotes: 2
Views: 4977
Reputation: 2545
I made a hook to persist column settings to localStorage. It uses callbacks on the API ref object. Usage:
function MyGrid() {
const apiRef = useGridApiRef()
usePersistColumnSettings(apiRef, 'customers-grid')
return <DataGrid apiRef={apiRef} />
}
Upvotes: 3
Reputation: 21
Fortunately, the DataGrid API provides the columnVisibilityModel
and onColumnVisibilityChange
props.
See this code sandbox for a simple example of controlling the columnVisibilityModel
: https://codesandbox.io/s/mui-datagrid-oncolumnvisibilitychange-savestate-u1opzc?file=/src/App.tsx:1960-1984
Here is the code for a simple implementation. Your initial state may vary. Also, note that I could not figure out how to get DataGridPro to call onColumnVisibilityChange
unless columnVisibilityModel
was initially undefined. Bug, or my mistake, I am uncertain.
import "./styles.css";
import React from "react";
import {
DataGrid,
GridRowsProp,
GridColDef,
GridCallbackDetails,
MuiEvent,
GridColumnVisibilityModel,
GridColumnVisibilityChangeParams
} from "@mui/x-data-grid";
import { Button } from "@mui/material";
const rows: GridRowsProp = [
{ id: 1, col1: "Hello", col2: "World" },
{ id: 2, col1: "DataGridPro", col2: "is Awesome" },
{ id: 3, col1: "MUI", col2: "is Amazing" }
];
const columns: GridColDef[] = [
{ field: "col1", headerName: "Column 1", width: 150 },
{ field: "col2", headerName: "Column 2", width: 150 }
];
const initialVisibilityModel = { col1: true, col2: true };
export default function App() {
// it is strange, but in order for DataGridPro to call onColumnVisibilityChange, columnVisibilityModel must be undefined initially
const [
currentGridColumnVisibilityModel,
setCurrentGridColumnVisibilityModel
] = React.useState<GridColumnVisibilityModel | undefined>(undefined);
const [mySavedValue, setMySavedValue] = React.useState<
GridColumnVisibilityModel | undefined
>(undefined);
const onColumnVisibilityChange = React.useCallback(
(
params: GridColumnVisibilityChangeParams,
event: MuiEvent<{}>,
details: GridCallbackDetails
): void => {
console.log("params", params);
setCurrentGridColumnVisibilityModel((s) => ({
// per the DataGridPro strangeness, we must marry in initial state only the first update
...(s ? s : initialVisibilityModel),
[params.field]: params.isVisible
}));
},
[]
);
const saveACopyOfGridState = () => {
setMySavedValue(currentGridColumnVisibilityModel || initialVisibilityModel);
};
const loadSavedCopyOfGridState = () => {
setCurrentGridColumnVisibilityModel(mySavedValue || initialVisibilityModel);
};
const currentVisibilityAsText =
`${Object.keys(currentGridColumnVisibilityModel ?? {}).map(
(key) => `{${key}:${currentGridColumnVisibilityModel?.[key]}}`
)}` || "empty";
const savedVisibilityAsText =
`${Object.keys(mySavedValue ?? {}).map(
(key) => `{${key}:${mySavedValue?.[key]}}`
)}` || "empty";
return (
<div style={{ height: 300, width: "100%" }}>
<DataGrid
rows={rows}
columns={columns}
columnVisibilityModel={currentGridColumnVisibilityModel}
onColumnVisibilityChange={onColumnVisibilityChange}
/>
<div>
<Button onClick={saveACopyOfGridState} variant="contained">
SAVE CURRENT COLUMN VISIBILITY STATE
</Button>
<Button
onClick={loadSavedCopyOfGridState}
variant="contained"
color="warning"
>
LOAD SAVED COLUMN VISIBILITY STATE
</Button>
</div>
<p>Current filter state: {currentVisibilityAsText}</p>
<p>Saved filter state: {savedVisibilityAsText}</p>
</div>
);
}
Upvotes: 2