Skip to content

Commit 69f0f3c

Browse files
[core] Allows to add custom export item (#3891)
1 parent 19fc801 commit 69f0f3c

File tree

9 files changed

+390
-104
lines changed

9 files changed

+390
-104
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import * as React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { useDemoData } from '@mui/x-data-grid-generator';
4+
import {
5+
DataGrid,
6+
GridToolbarContainer,
7+
GridToolbarExportContainer,
8+
GridCsvExportMenuItem,
9+
useGridApiContext,
10+
gridFilteredSortedRowIdsSelector,
11+
visibleGridColumnsSelector,
12+
} from '@mui/x-data-grid';
13+
import MenuItem from '@mui/material/MenuItem';
14+
15+
const getJson = (apiRef) => {
16+
// Select rows and columns
17+
const filteredSortedRowIds = gridFilteredSortedRowIdsSelector(apiRef);
18+
const visibleColumnsField = visibleGridColumnsSelector(apiRef).map(
19+
(col) => col.field,
20+
);
21+
22+
// Format the data. Here we only keep the value
23+
const data = filteredSortedRowIds.map((id) => {
24+
const row = {};
25+
visibleColumnsField.forEach((field) => {
26+
row[field] = apiRef.current.getCellParams(id, field).value;
27+
});
28+
return row;
29+
});
30+
31+
// Stringify with some indentation
32+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#parameters
33+
return JSON.stringify(data, null, 2);
34+
};
35+
36+
const exportBlob = (blob, filename) => {
37+
// Save the blob in a json file
38+
const url = URL.createObjectURL(blob);
39+
40+
const a = document.createElement('a');
41+
a.href = url;
42+
a.download = filename;
43+
a.click();
44+
45+
setTimeout(() => {
46+
URL.revokeObjectURL(url);
47+
});
48+
};
49+
50+
const JsonExportMenuItem = (props) => {
51+
const apiRef = useGridApiContext();
52+
53+
const { hideMenu } = props;
54+
55+
return (
56+
<MenuItem
57+
onClick={() => {
58+
const jsonString = getJson(apiRef);
59+
const blob = new Blob([jsonString], {
60+
type: 'text/json',
61+
});
62+
63+
exportBlob(blob, 'DataGrid_demo.json');
64+
65+
// Hide the export menu after the export
66+
hideMenu?.();
67+
}}
68+
>
69+
Export JSON
70+
</MenuItem>
71+
);
72+
};
73+
74+
JsonExportMenuItem.propTypes = {
75+
hideMenu: PropTypes.func,
76+
};
77+
78+
const csvOptions = { delimiter: ';' };
79+
80+
const CustomExportButton = (props) => (
81+
<GridToolbarExportContainer {...props}>
82+
<GridCsvExportMenuItem options={csvOptions} />
83+
<JsonExportMenuItem />
84+
</GridToolbarExportContainer>
85+
);
86+
87+
const CustomToolbar = (props) => (
88+
<GridToolbarContainer {...props}>
89+
<CustomExportButton />
90+
</GridToolbarContainer>
91+
);
92+
93+
export default function CustomExport() {
94+
const { data, loading } = useDemoData({
95+
dataSet: 'Commodity',
96+
rowLength: 4,
97+
maxColumns: 6,
98+
});
99+
100+
return (
101+
<div style={{ height: 300, width: '100%' }}>
102+
<DataGrid
103+
{...data}
104+
loading={loading}
105+
components={{ Toolbar: CustomToolbar }}
106+
/>
107+
</div>
108+
);
109+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import * as React from 'react';
2+
import { useDemoData } from '@mui/x-data-grid-generator';
3+
import {
4+
DataGrid,
5+
GridToolbarContainer,
6+
GridToolbarContainerProps,
7+
GridToolbarExportContainer,
8+
GridCsvExportMenuItem,
9+
GridCsvExportOptions,
10+
GridExportMenuItemProps,
11+
useGridApiContext,
12+
gridFilteredSortedRowIdsSelector,
13+
visibleGridColumnsSelector,
14+
} from '@mui/x-data-grid';
15+
import MenuItem from '@mui/material/MenuItem';
16+
import { ButtonProps } from '@mui/material/Button';
17+
18+
const getJson = (apiRef) => {
19+
// Select rows and columns
20+
const filteredSortedRowIds = gridFilteredSortedRowIdsSelector(apiRef);
21+
const visibleColumnsField = visibleGridColumnsSelector(apiRef).map(
22+
(col) => col.field,
23+
);
24+
25+
// Format the data. Here we only keep the value
26+
const data = filteredSortedRowIds.map((id) => {
27+
const row = {};
28+
visibleColumnsField.forEach((field) => {
29+
row[field] = apiRef.current.getCellParams(id, field).value;
30+
});
31+
return row;
32+
});
33+
34+
// Stringify with some indentation
35+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#parameters
36+
return JSON.stringify(data, null, 2);
37+
};
38+
39+
const exportBlob = (blob, filename) => {
40+
// Save the blob in a json file
41+
const url = URL.createObjectURL(blob);
42+
43+
const a = document.createElement('a');
44+
a.href = url;
45+
a.download = filename;
46+
a.click();
47+
48+
setTimeout(() => {
49+
URL.revokeObjectURL(url);
50+
});
51+
};
52+
53+
const JsonExportMenuItem = (props: GridExportMenuItemProps<{}>) => {
54+
const apiRef = useGridApiContext();
55+
56+
const { hideMenu } = props;
57+
58+
return (
59+
<MenuItem
60+
onClick={() => {
61+
const jsonString = getJson(apiRef);
62+
const blob = new Blob([jsonString], {
63+
type: 'text/json',
64+
});
65+
exportBlob(blob, 'DataGrid_demo.json');
66+
67+
// Hide the export menu after the export
68+
hideMenu?.();
69+
}}
70+
>
71+
Export JSON
72+
</MenuItem>
73+
);
74+
};
75+
76+
const csvOptions: GridCsvExportOptions = { delimiter: ';' };
77+
78+
const CustomExportButton = (props: ButtonProps) => (
79+
<GridToolbarExportContainer {...props}>
80+
<GridCsvExportMenuItem options={csvOptions} />
81+
<JsonExportMenuItem />
82+
</GridToolbarExportContainer>
83+
);
84+
85+
const CustomToolbar = (props: GridToolbarContainerProps) => (
86+
<GridToolbarContainer {...props}>
87+
<CustomExportButton />
88+
</GridToolbarContainer>
89+
);
90+
91+
export default function CustomExport() {
92+
const { data, loading } = useDemoData({
93+
dataSet: 'Commodity',
94+
rowLength: 4,
95+
maxColumns: 6,
96+
});
97+
98+
return (
99+
<div style={{ height: 300, width: '100%' }}>
100+
<DataGrid
101+
{...data}
102+
loading={loading}
103+
components={{ Toolbar: CustomToolbar }}
104+
/>
105+
</div>
106+
);
107+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<DataGrid
2+
{...data}
3+
loading={loading}
4+
components={{ Toolbar: CustomToolbar }}
5+
/>

docs/data/data-grid/export/export.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,26 @@ By default, the print export display all the DataGrid. It is possible to remove
165165

166166
For more option to customize the print export, please visit the [`printOptions` api page](/api/data-grid/grid-print-export-options/).
167167

168+
## Custom export format
169+
170+
You can add custom export formats by creating your own export menu.
171+
To simplify its creation, we export `<GridToolbarExportContainer />` which contains the menu logic.
172+
The default `<GridToolbarExport />` is defined as follow:
173+
174+
```jsx
175+
const GridToolbarExport = ({ csvOptions, printOptions, ...other }) => (
176+
<GridToolbarExportContainer {...other}>
177+
<GridCsvExportMenuItem options={csvOptions} />
178+
<GridPrintExportMenuItem options={printOptions} />
179+
</GridToolbarExportContainer>
180+
);
181+
```
182+
183+
Each child of the `<GridToolbarExportContainer />` receives a prop `hideMenu` to close the export menu after the export.
184+
The demo below shows how to add a JSON export.
185+
186+
{{"demo": "CustomExport.js", "bg": "inline", "defaultCodeOpen": false}}
187+
168188
## 🚧 Excel export [<span class="plan-premium"></span>](https://mui.com/store/items/material-ui-pro/)
169189

170190
> ⚠️ This feature isn't implemented yet. It's coming.

0 commit comments

Comments
 (0)