Skip to content

Commit

Permalink
[DataGrid] Add resetPageOnSortFilter prop that resets the page afte…
Browse files Browse the repository at this point in the history
…r sorting/filtering (@arminmeh) (#16580)

Signed-off-by: Armin Mehinovic <[email protected]>
Co-authored-by: Armin Mehinovic <[email protected]>
Co-authored-by: Bilal Shafi <[email protected]>
Co-authored-by: Sam Sycamore <[email protected]>
Co-authored-by: Armin Mehinovic <[email protected]>
  • Loading branch information
5 people authored Feb 16, 2025
1 parent 7564ded commit 73ded3e
Show file tree
Hide file tree
Showing 26 changed files with 497 additions and 17 deletions.
30 changes: 30 additions & 0 deletions docs/data/data-grid/filtering/FilteringWithPageReset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as React from 'react';
import { DataGrid, GridToolbar } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin'];

export default function FilteringWithPageReset() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
visibleFields: VISIBLE_FIELDS,
rowLength: 100,
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
{...data}
loading={loading}
pagination
initialState={{
...data.initialState,
pagination: { paginationModel: { page: 0, pageSize: 10 } },
}}
pageSizeOptions={[10]}
resetPageOnSortFilter
slots={{ toolbar: GridToolbar }}
/>
</div>
);
}
30 changes: 30 additions & 0 deletions docs/data/data-grid/filtering/FilteringWithPageReset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as React from 'react';
import { DataGrid, GridToolbar } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin'];

export default function FilteringWithPageReset() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
visibleFields: VISIBLE_FIELDS,
rowLength: 100,
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
{...data}
loading={loading}
pagination
initialState={{
...data.initialState,
pagination: { paginationModel: { page: 0, pageSize: 10 } },
}}
pageSizeOptions={[10]}
resetPageOnSortFilter
slots={{ toolbar: GridToolbar }}
/>
</div>
);
}
12 changes: 12 additions & 0 deletions docs/data/data-grid/filtering/FilteringWithPageReset.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<DataGrid
{...data}
loading={loading}
pagination
initialState={{
...data.initialState,
pagination: { paginationModel: { page: 0, pageSize: 10 } },
}}
pageSizeOptions={[10]}
resetPageOnSortFilter
slots={{ toolbar: GridToolbar }}
/>
8 changes: 8 additions & 0 deletions docs/data/data-grid/filtering/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ const columns = [

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

## Reset page on filtering

By default, the user stays on the same page after a filter is applied, unless the new row count indicates that that page doesn't exist anymore.
In that case, the user is sent to the last page as defined by the new row count.
To send the user back to the first page when a new filter is applied, use the `resetPageOnSortFilter` prop.

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

## Ignore diacritics (accents)

You can ignore diacritics (accents) when filtering the rows. See [Quick filter - Ignore diacritics (accents)](/x/react-data-grid/filtering/quick-filter/#ignore-diacritics-accents).
Expand Down
4 changes: 4 additions & 0 deletions docs/data/data-grid/filtering/server-side.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ The example below demonstrates how to achieve server-side filtering.

{{"demo": "ServerFilterGrid.js", "bg": "inline"}}

:::success
You can combine server-side filtering with [server-side sorting](/x/react-data-grid/sorting/#server-side-sorting) and [server-side pagination](/x/react-data-grid/pagination/#server-side-pagination) to avoid fetching more data than needed, since it's already processed outside of the Data Grid.
:::

## API

- [DataGrid](/x/api/data-grid/data-grid/)
Expand Down
57 changes: 57 additions & 0 deletions docs/data/data-grid/pagination/ServerPaginationFilterSortGrid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { createFakeServer } from '@mui/x-data-grid-generator';

const SERVER_OPTIONS = {
useCursorPagination: false,
};

const { useQuery, ...data } = createFakeServer({}, SERVER_OPTIONS);

export default function ServerPaginationFilterSortGrid() {
const [paginationModel, setPaginationModel] = React.useState({
page: 0,
pageSize: 5,
});
const [sortModel, setSortModel] = React.useState([]);
const [filterModel, setFilterModel] = React.useState({
items: [],
});
const queryOptions = React.useMemo(
() => ({ ...paginationModel, sortModel, filterModel }),
[paginationModel, sortModel, filterModel],
);
const { isLoading, rows, pageInfo } = useQuery(queryOptions);

// Some API clients return undefined while loading
// Following lines are here to prevent `rowCount` from being undefined during the loading
const rowCountRef = React.useRef(pageInfo?.totalRowCount || 0);

const rowCount = React.useMemo(() => {
if (pageInfo?.totalRowCount !== undefined) {
rowCountRef.current = pageInfo.totalRowCount;
}
return rowCountRef.current;
}, [pageInfo?.totalRowCount]);

return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={rows}
{...data}
rowCount={rowCount}
loading={isLoading}
pageSizeOptions={[5]}
paginationModel={paginationModel}
sortModel={sortModel}
filterModel={filterModel}
paginationMode="server"
sortingMode="server"
filterMode="server"
onPaginationModelChange={setPaginationModel}
onSortModelChange={setSortModel}
onFilterModelChange={setFilterModel}
/>
</div>
);
}
57 changes: 57 additions & 0 deletions docs/data/data-grid/pagination/ServerPaginationFilterSortGrid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as React from 'react';
import { DataGrid, GridSortModel, GridFilterModel } from '@mui/x-data-grid';
import { createFakeServer } from '@mui/x-data-grid-generator';

const SERVER_OPTIONS = {
useCursorPagination: false,
};

const { useQuery, ...data } = createFakeServer({}, SERVER_OPTIONS);

export default function ServerPaginationFilterSortGrid() {
const [paginationModel, setPaginationModel] = React.useState({
page: 0,
pageSize: 5,
});
const [sortModel, setSortModel] = React.useState<GridSortModel>([]);
const [filterModel, setFilterModel] = React.useState<GridFilterModel>({
items: [],
});
const queryOptions = React.useMemo(
() => ({ ...paginationModel, sortModel, filterModel }),
[paginationModel, sortModel, filterModel],
);
const { isLoading, rows, pageInfo } = useQuery(queryOptions);

// Some API clients return undefined while loading
// Following lines are here to prevent `rowCount` from being undefined during the loading
const rowCountRef = React.useRef(pageInfo?.totalRowCount || 0);

const rowCount = React.useMemo(() => {
if (pageInfo?.totalRowCount !== undefined) {
rowCountRef.current = pageInfo.totalRowCount;
}
return rowCountRef.current;
}, [pageInfo?.totalRowCount]);

return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={rows}
{...data}
rowCount={rowCount}
loading={isLoading}
pageSizeOptions={[5]}
paginationModel={paginationModel}
sortModel={sortModel}
filterModel={filterModel}
paginationMode="server"
sortingMode="server"
filterMode="server"
onPaginationModelChange={setPaginationModel}
onSortModelChange={setSortModel}
onFilterModelChange={setFilterModel}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<DataGrid
rows={rows}
{...data}
rowCount={rowCount}
loading={isLoading}
pageSizeOptions={[5]}
paginationModel={paginationModel}
sortModel={sortModel}
filterModel={filterModel}
paginationMode="server"
sortingMode="server"
filterMode="server"
onPaginationModelChange={setPaginationModel}
onSortModelChange={setSortModel}
onFilterModelChange={setFilterModel}
/>
8 changes: 8 additions & 0 deletions docs/data/data-grid/pagination/pagination.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ By default, the pagination is handled on the client.
This means you have to give the rows of all pages to the Data Grid.
If your dataset is too big, and you want to fetch the pages on demand, you can use server-side pagination.

:::warning
If you enable server-side pagination with no other server-side features, then the Data Grid will only be provided with partial data for filtering and sorting.
To be able to work with the entire dataset, you must also implement [server-side filtering](/x/react-data-grid/filtering/server-side/) and [server-side sorting](/x/react-data-grid/sorting/#server-side-sorting).
The demo below does exactly that.
:::

{{"demo": "ServerPaginationFilterSortGrid.js", "bg": "inline"}}

In general, the server-side pagination could be categorized into two types:

- Index-based pagination
Expand Down
26 changes: 26 additions & 0 deletions docs/data/data-grid/sorting/SortingWithPageReset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin'];

export default function SortingWithPageReset() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
visibleFields: VISIBLE_FIELDS,
rowLength: 100,
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
{...data}
loading={loading}
pagination
pageSizeOptions={[10]}
initialState={{ pagination: { paginationModel: { page: 0, pageSize: 10 } } }}
resetPageOnSortFilter
/>
</div>
);
}
26 changes: 26 additions & 0 deletions docs/data/data-grid/sorting/SortingWithPageReset.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin'];

export default function SortingWithPageReset() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
visibleFields: VISIBLE_FIELDS,
rowLength: 100,
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
{...data}
loading={loading}
pagination
pageSizeOptions={[10]}
initialState={{ pagination: { paginationModel: { page: 0, pageSize: 10 } } }}
resetPageOnSortFilter
/>
</div>
);
}
8 changes: 8 additions & 0 deletions docs/data/data-grid/sorting/SortingWithPageReset.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<DataGrid
{...data}
loading={loading}
pagination
pageSizeOptions={[10]}
initialState={{ pagination: { paginationModel: { page: 0, pageSize: 10 } } }}
resetPageOnSortFilter
/>
11 changes: 11 additions & 0 deletions docs/data/data-grid/sorting/sorting.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ In the following demo, the `firstName` column is not sortable by the default gri

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

## Reset page on sorting

By default, sorting does not change the current page.
To send the user back to the first page when a new sort is applied, use the `resetPageOnSortFilter` prop.

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

## Custom comparator

A comparator determines how two cell values should be sorted.
Expand Down Expand Up @@ -164,6 +171,10 @@ Sorting can be run server-side by setting the `sortingMode` prop to `server`, an

{{"demo": "ServerSortingGrid.js", "bg": "inline"}}

:::success
You can combine server-side sorting with [server-side filtering](/x/react-data-grid/filtering/server-side/) and [server-side pagination](/x/react-data-grid/pagination/#server-side-pagination) to avoid fetching more data than needed, since it's already processed outside of the Data Grid.
:::

## apiRef

:::warning
Expand Down
1 change: 1 addition & 0 deletions docs/pages/x/api/data-grid/data-grid-premium.json
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@
"returned": "Promise<R> | R"
}
},
"resetPageOnSortFilter": { "type": { "name": "bool" }, "default": "false" },
"resizeThrottleMs": { "type": { "name": "number" }, "default": "60" },
"rowBufferPx": { "type": { "name": "number" }, "default": "150" },
"rowCount": { "type": { "name": "number" } },
Expand Down
1 change: 1 addition & 0 deletions docs/pages/x/api/data-grid/data-grid-pro.json
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@
"returned": "Promise<R> | R"
}
},
"resetPageOnSortFilter": { "type": { "name": "bool" }, "default": "false" },
"resizeThrottleMs": { "type": { "name": "number" }, "default": "60" },
"rowBufferPx": { "type": { "name": "number" }, "default": "150" },
"rowCount": { "type": { "name": "number" } },
Expand Down
1 change: 1 addition & 0 deletions docs/pages/x/api/data-grid/data-grid.json
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@
"returned": "Promise<R> | R"
}
},
"resetPageOnSortFilter": { "type": { "name": "bool" }, "default": "false" },
"resizeThrottleMs": { "type": { "name": "number" }, "default": "60" },
"rowBufferPx": { "type": { "name": "number" }, "default": "150" },
"rowCount": { "type": { "name": "number" } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,9 @@
"Promise<R> | R": "The final values to update the row."
}
},
"resetPageOnSortFilter": {
"description": "If <code>true</code>, the page is set to 0 after each sorting or filtering. This prop will be removed in the next major version and resetting the page will become the default behavior."
},
"resizeThrottleMs": { "description": "The milliseconds throttle delay for resizing the grid." },
"rowBufferPx": { "description": "Row region in pixels to render before/after the viewport" },
"rowCount": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,9 @@
"Promise<R> | R": "The final values to update the row."
}
},
"resetPageOnSortFilter": {
"description": "If <code>true</code>, the page is set to 0 after each sorting or filtering. This prop will be removed in the next major version and resetting the page will become the default behavior."
},
"resizeThrottleMs": { "description": "The milliseconds throttle delay for resizing the grid." },
"rowBufferPx": { "description": "Row region in pixels to render before/after the viewport" },
"rowCount": {
Expand Down
3 changes: 3 additions & 0 deletions docs/translations/api-docs/data-grid/data-grid/data-grid.json
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,9 @@
"Promise<R> | R": "The final values to update the row."
}
},
"resetPageOnSortFilter": {
"description": "If <code>true</code>, the page is set to 0 after each sorting or filtering. This prop will be removed in the next major version and resetting the page will become the default behavior."
},
"resizeThrottleMs": { "description": "The milliseconds throttle delay for resizing the grid." },
"rowBufferPx": { "description": "Row region in pixels to render before/after the viewport" },
"rowCount": {
Expand Down
Loading

0 comments on commit 73ded3e

Please sign in to comment.