Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGridPremium] Server-side data source with row grouping #13826

Open
wants to merge 43 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ac19bcd
[DataGridPremium] Server-side row grouping
MBilalShafi Jul 15, 2024
b83928f
Lint
MBilalShafi Jul 15, 2024
222da23
Merge branch 'master' into datasource-row-grouping
MBilalShafi Sep 4, 2024
d8b762b
Adjust according to the changes done on master
MBilalShafi Sep 4, 2024
26ed96e
Support sort and filter on normal non-grouping columns
MBilalShafi Sep 6, 2024
bb06da1
Merge branch 'master' into datasource-row-grouping
MBilalShafi Sep 6, 2024
ad92678
Update documentation
MBilalShafi Sep 6, 2024
02d1ab3
Update tag
MBilalShafi Sep 6, 2024
342594a
Docs update
MBilalShafi Sep 7, 2024
435ecdf
Merge branch 'master' into datasource-row-grouping
MBilalShafi Sep 9, 2024
5d4220d
Add support for groupingValueGetter
MBilalShafi Sep 9, 2024
58daf43
Merge branch 'master' into datasource-row-grouping
MBilalShafi Sep 12, 2024
d1712de
Typo
MBilalShafi Sep 12, 2024
66ab0c8
Support rows with missing groups on mock server
MBilalShafi Sep 12, 2024
f072523
Fix argos' regression
MBilalShafi Sep 12, 2024
7580c46
Lint
MBilalShafi Sep 12, 2024
3780ddd
Update sidebar
MBilalShafi Sep 12, 2024
c92106d
Improve some documentation
MBilalShafi Sep 12, 2024
43c6e16
Enable client side aggregation
MBilalShafi Sep 12, 2024
0160a0a
Cleanup
MBilalShafi Sep 13, 2024
4e832b3
Docs updates
MBilalShafi Sep 13, 2024
5f6f0c6
Add commodities demo
MBilalShafi Sep 13, 2024
779b29d
Add toolbar to the demo
MBilalShafi Sep 14, 2024
b1a955c
Remove in-progress icon
MBilalShafi Sep 14, 2024
7dd206d
Add info section to docs
MBilalShafi Sep 16, 2024
d3aad07
Docs improvement
MBilalShafi Sep 16, 2024
ed631de
Support expansion using keyboard
MBilalShafi Sep 16, 2024
17f9f33
Update
MBilalShafi Sep 16, 2024
966718e
Merge branch 'master' into datasource-row-grouping
MBilalShafi Sep 20, 2024
e1f7a6a
Rename constants
MBilalShafi Sep 20, 2024
900e127
Make the selector memoized
MBilalShafi Sep 28, 2024
74ff1de
Merge branch 'master' into datasource-row-grouping
MBilalShafi Sep 28, 2024
c9fec5a
Merge branch 'master' into datasource-row-grouping
MBilalShafi Oct 3, 2024
5303c54
Merge branch 'master' into datasource-row-grouping
MBilalShafi Oct 11, 2024
509d264
Resolve a few comments
MBilalShafi Oct 11, 2024
0744856
Update documentation
MBilalShafi Oct 11, 2024
5f929f1
Fix types + lint
MBilalShafi Oct 11, 2024
8c623d0
Use pipe processing for row grouping params
MBilalShafi Oct 11, 2024
c60b757
Update a line of doc
MBilalShafi Oct 11, 2024
6ee149a
Merge branch 'master' into datasource-row-grouping
MBilalShafi Oct 17, 2024
ba0ab94
Use enums
MBilalShafi Oct 18, 2024
d685bb4
Merge branch 'master' into datasource-row-grouping
MBilalShafi Oct 21, 2024
7491df5
Adjust as per #15013
MBilalShafi Oct 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions docs/data/data-grid/row-grouping/row-grouping.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ In the following example, movies are grouped based on their production `company`

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

:::info
If you are looking for row grouping on the server-side, see [server-side row grouping](/x/react-data-grid/server-side-data/row-grouping/).
:::

## Grouping criteria

### Initialize the row grouping
Expand Down Expand Up @@ -252,6 +256,10 @@ Use the `setRowChildrenExpansion` method on `apiRef` to programmatically set the

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

:::warning
The `apiRef.current.setRowChildrenExpansion` method is not compatible with the [server-side tree data](/x/react-data-grid/server-side-data/tree-data/) and [server-side row grouping](/x/react-data-grid/server-side-data/row-grouping/). Use `apiRef.current.unstable_dataSource.fetchRows` instead.
:::

### Customize grouping cell indent

To change the default cell indent, you can use the `--DataGrid-cellOffsetMultiplier` CSS variable:
Expand Down Expand Up @@ -280,10 +288,6 @@ If you are rendering leaves with the `leafField` property of `groupingColDef`, t

You can force the filtering to be applied on another grouping criteria with the `mainGroupingCriteria` property of `groupingColDef`

:::warning
This feature is not yet compatible with `sortingMode = "server"` and `filteringMode = "server"`.
:::

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

### Multiple grouping columns
Expand Down Expand Up @@ -376,6 +380,10 @@ const rows = apiRef.current.getRowGroupChildren({

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

:::warning
The `apiRef.current.getRowGroupChildren` method is not compatible with the [server-side row grouping](/x/react-data-grid/server-side-data/row-grouping/) since all the rows might not be available to get at a given instance.
:::

## Row group panel 🚧

:::warning
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as React from 'react';
import {
DataGridPremium,
useGridApiRef,
useKeepGroupedColumnsHidden,
} from '@mui/x-data-grid-premium';
import { useMockServer } from '@mui/x-data-grid-generator';
import Button from '@mui/material/Button';

export default function ServerSideRowGroupingDataGrid() {
const apiRef = useGridApiRef();

const { fetchRows, columns } = useMockServer({
rowGrouping: true,
});

const dataSource = React.useMemo(() => {
return {
getRows: async (params) => {
const urlParams = new URLSearchParams({
paginationModel: JSON.stringify(params.paginationModel),
filterModel: JSON.stringify(params.filterModel),
sortModel: JSON.stringify(params.sortModel),
groupKeys: JSON.stringify(params.groupKeys),
groupFields: JSON.stringify(params.groupFields),
});
const getRowsResponse = await fetchRows(
`https://mui.com/x/api/data-grid?${urlParams.toString()}`,
);
return {
rows: getRowsResponse.rows,
rowCount: getRowsResponse.rowCount,
};
},
getGroupKey: (row) => row.group,
getChildrenCount: (row) => row.descendantCount,
};
}, [fetchRows]);

const initialState = useKeepGroupedColumnsHidden({
apiRef,
initialState: {
rowGrouping: {
model: ['company', 'director'],
},
},
});

return (
<div style={{ width: '100%' }}>
<Button
onClick={() => {
apiRef.current.unstable_dataSource.cache.clear();
}}
>
Clear cache
</Button>

<div style={{ height: 400, position: 'relative' }}>
<DataGridPremium
columns={columns}
unstable_dataSource={dataSource}
apiRef={apiRef}
initialState={initialState}
/>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import * as React from 'react';
import {
DataGridPremium,
GridDataSource,
useGridApiRef,
useKeepGroupedColumnsHidden,
} from '@mui/x-data-grid-premium';
import { useMockServer } from '@mui/x-data-grid-generator';
import Button from '@mui/material/Button';

export default function ServerSideRowGroupingDataGrid() {
const apiRef = useGridApiRef();

const { fetchRows, columns } = useMockServer({
rowGrouping: true,
});

const dataSource: GridDataSource = React.useMemo(() => {
return {
getRows: async (params) => {
const urlParams = new URLSearchParams({
paginationModel: JSON.stringify(params.paginationModel),
filterModel: JSON.stringify(params.filterModel),
sortModel: JSON.stringify(params.sortModel),
groupKeys: JSON.stringify(params.groupKeys),
groupFields: JSON.stringify(params.groupFields),
});
const getRowsResponse = await fetchRows(
`https://mui.com/x/api/data-grid?${urlParams.toString()}`,
);
return {
rows: getRowsResponse.rows,
rowCount: getRowsResponse.rowCount,
};
},
getGroupKey: (row) => row.group,
getChildrenCount: (row) => row.descendantCount,
};
}, [fetchRows]);

const initialState = useKeepGroupedColumnsHidden({
apiRef,
initialState: {
rowGrouping: {
model: ['company', 'director'],
},
},
});

return (
<div style={{ width: '100%' }}>
<Button
onClick={() => {
apiRef.current.unstable_dataSource.cache.clear();
}}
>
Clear cache
</Button>

<div style={{ height: 400, position: 'relative' }}>
<DataGridPremium
columns={columns}
unstable_dataSource={dataSource}
apiRef={apiRef}
initialState={initialState}
/>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Button
onClick={() => {
apiRef.current.unstable_dataSource.cache.clear();
}}
>
Clear cache
</Button>

<div style={{ height: 400, position: 'relative' }}>
<DataGridPremium
columns={columns}
unstable_dataSource={dataSource}
apiRef={apiRef}
initialState={initialState}
/>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import * as React from 'react';
import {
DataGridPremium,
useGridApiRef,
useKeepGroupedColumnsHidden,
} from '@mui/x-data-grid-premium';
import { useMockServer } from '@mui/x-data-grid-generator';
import Snackbar from '@mui/material/Snackbar';
import Button from '@mui/material/Button';
import Checkbox from '@mui/material/Checkbox';
import FormControlLabel from '@mui/material/FormControlLabel';
import { alpha, styled, darken, lighten } from '@mui/material/styles';

export default function ServerSideRowGroupingErrorHandling() {
const apiRef = useGridApiRef();
const [rootError, setRootError] = React.useState();
const [childrenError, setChildrenError] = React.useState();
const [shouldRequestsFail, setShouldRequestsFail] = React.useState(false);

const { fetchRows, columns } = useMockServer(
{
rowGrouping: true,
},
{},
shouldRequestsFail,
);

const dataSource = React.useMemo(() => {
return {
getRows: async (params) => {
const urlParams = new URLSearchParams({
paginationModel: JSON.stringify(params.paginationModel),
filterModel: JSON.stringify(params.filterModel),
sortModel: JSON.stringify(params.sortModel),
groupKeys: JSON.stringify(params.groupKeys),
groupFields: JSON.stringify(params.groupFields),
});
const getRowsResponse = await fetchRows(
`https://mui.com/x/api/data-grid?${urlParams.toString()}`,
);
return {
rows: getRowsResponse.rows,
rowCount: getRowsResponse.rowCount,
};
},
getGroupKey: (row) => row.group,
getChildrenCount: (row) => row.descendantCount,
};
}, [fetchRows]);

const initialState = useKeepGroupedColumnsHidden({
apiRef,
initialState: {
rowGrouping: {
model: ['company', 'director'],
},
},
});

return (
<div style={{ width: '100%' }}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Button
onClick={() => {
setRootError('');
apiRef.current.unstable_dataSource.fetchRows();
}}
>
Refetch rows
</Button>
<FormControlLabel
control={
<Checkbox
checked={shouldRequestsFail}
onChange={(event) => setShouldRequestsFail(event.target.checked)}
/>
}
label="Make the requests fail"
/>
</div>
<div style={{ height: 400, position: 'relative' }}>
<DataGridPremium
columns={columns}
unstable_dataSource={dataSource}
unstable_onDataSourceError={(error, params) => {
if (!params.groupKeys || params.groupKeys.length === 0) {
setRootError(error.message);
} else {
setChildrenError(
`${error.message} (Requested level: ${params.groupKeys.join(' > ')})`,
);
}
}}
unstable_dataSourceCache={null}
apiRef={apiRef}
initialState={initialState}
/>
{rootError && <ErrorOverlay error={rootError} />}
<Snackbar
open={!!childrenError}
autoHideDuration={3000}
onClose={() => setChildrenError('')}
message={childrenError}
/>
</div>
</div>
);
}

function getBorderColor(theme) {
if (theme.palette.mode === 'light') {
return lighten(alpha(theme.palette.divider, 1), 0.88);
}
return darken(alpha(theme.palette.divider, 1), 0.68);
}

const StyledDiv = styled('div')(({ theme: t }) => ({
position: 'absolute',
zIndex: 10,
fontSize: '0.875em',
top: 0,
height: '100%',
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
borderRadius: '4px',
border: `1px solid ${getBorderColor(t)}`,
backgroundColor: t.palette.background.default,
}));

function ErrorOverlay({ error }) {
if (!error) {
return null;
}
return <StyledDiv>{error}</StyledDiv>;
}
Loading