diff --git a/docs/src/pages.js b/docs/src/pages.js index 544edb183d7d5..2ece1d18c0524 100644 --- a/docs/src/pages.js +++ b/docs/src/pages.js @@ -146,7 +146,7 @@ const pages = [ { pathname: '/components/data-grid/rendering' }, { pathname: '/components/data-grid/export', title: 'Export & Import' }, { pathname: '/components/data-grid/localization' }, - { pathname: '/components/data-grid/group-pivot', title: 'Group & Pivot' }, + { pathname: '/components/data-grid/group-pivot', title: 'Group & Pivot ✨' }, { pathname: '/components/data-grid/accessibility' }, ], }, diff --git a/docs/src/pages/components/data-grid/pagination/ApiRefPaginationGrid.js b/docs/src/pages/components/data-grid/pagination/ApiRefPaginationGrid.js new file mode 100644 index 0000000000000..7455b6046a20e --- /dev/null +++ b/docs/src/pages/components/data-grid/pagination/ApiRefPaginationGrid.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import { DataGrid, useApiRef } from '@material-ui/data-grid'; +import { useDemoData } from '@material-ui/x-grid-data-generator'; + +export default function ApiRefPaginationGrid() { + const apiRef = useApiRef(); + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 10, + maxColumns: 6, + }); + + React.useEffect(() => { + console.log('hello', apiRef.current); + apiRef.current.setPage(2); + }, [apiRef]); + + return ( +
+ +
+ ); +} diff --git a/docs/src/pages/components/data-grid/pagination/ApiRefPaginationGrid.tsx b/docs/src/pages/components/data-grid/pagination/ApiRefPaginationGrid.tsx new file mode 100644 index 0000000000000..13427210a2a6a --- /dev/null +++ b/docs/src/pages/components/data-grid/pagination/ApiRefPaginationGrid.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import { DataGrid, useApiRef } from '@material-ui/data-grid'; +import { useDemoData } from '@material-ui/x-grid-data-generator'; + +export default function ApiRefPaginationGrid() { + const apiRef = useApiRef(); + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 10, + maxColumns: 6, + }); + + React.useEffect(() => { + console.log('hello', apiRef.current) + apiRef.current.setPage(2); + }, [apiRef]); + + return ( +
+ +
+ ); +} diff --git a/docs/src/pages/components/data-grid/pagination/ServerPaginationGrid.js b/docs/src/pages/components/data-grid/pagination/ServerPaginationGrid.js new file mode 100644 index 0000000000000..5588c586fc47d --- /dev/null +++ b/docs/src/pages/components/data-grid/pagination/ServerPaginationGrid.js @@ -0,0 +1,62 @@ +import * as React from 'react'; +import { DataGrid } from '@material-ui/data-grid'; +import { useDemoData } from '@material-ui/x-grid-data-generator'; + +function loadServerRows(page, data) { + return new Promise((resolve) => { + setTimeout(() => { + resolve(data.rows.slice((page - 1) * 5, page * 5)); + }, Math.random() * 500 + 100); + }); +} + +export default function ServerPaginationGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 6, + }); + + const [page, setPage] = React.useState(1); + const [rows, setRows] = React.useState([]); + const [loading, setLoading] = React.useState(false); + + const handlePageChange = (params) => { + setPage(params.page); + }; + + React.useEffect(() => { + let active = true; + + (async () => { + setLoading(true); + const newRows = await loadServerRows(page, data); + + if (!active) { + return; + } + + setRows(newRows); + setLoading(false); + })(); + + return () => { + active = false; + }; + }, [page, data]); + + return ( +
+ +
+ ); +} diff --git a/docs/src/pages/components/data-grid/pagination/ServerPaginationGrid.tsx b/docs/src/pages/components/data-grid/pagination/ServerPaginationGrid.tsx new file mode 100644 index 0000000000000..43b98a9b64ec2 --- /dev/null +++ b/docs/src/pages/components/data-grid/pagination/ServerPaginationGrid.tsx @@ -0,0 +1,61 @@ +import * as React from 'react'; +import { RowsProp, DataGrid } from '@material-ui/data-grid'; +import { useDemoData, GridData } from '@material-ui/x-grid-data-generator'; + +function loadServerRows(page: number, data: GridData): Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve(data.rows.slice((page - 1) * 5, page * 5)); + }, Math.random() * 500 + 100); + }); +} + +export default function ServerPaginationGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 6, + }); + const [page, setPage] = React.useState(1); + const [rows, setRows] = React.useState([]); + const [loading, setLoading] = React.useState(false); + + const handlePageChange = (params) => { + setPage(params.page); + }; + + React.useEffect(() => { + let active = true; + + (async () => { + setLoading(true); + const newRows = await loadServerRows(page, data); + + if (!active) { + return; + } + + setRows(newRows); + setLoading(false); + })(); + + return () => { + active = false; + }; + }, [page, data]); + + return ( +
+ +
+ ); +} diff --git a/docs/src/pages/components/data-grid/pagination/pagination.md b/docs/src/pages/components/data-grid/pagination/pagination.md index 2739ecdd03bba..b9b555a2ecb56 100644 --- a/docs/src/pages/components/data-grid/pagination/pagination.md +++ b/docs/src/pages/components/data-grid/pagination/pagination.md @@ -41,11 +41,19 @@ Head to the [rendering section](/components/data-grid/rendering/#pagination) of ## Server-side pagination -- https://ej2.syncfusion.com/react/demos/#/material/grid/paging -- https://devexpress.github.io/devextreme-reactive/react/grid/docs/guides/paging/ -- https://www.telerik.com/kendo-react-ui/components/grid/paging/ -- https://ag-grid.com/javascript-grid-pagination/ -- https://github.com/tannerlinsley/react-table/blob/master/docs/api/usePagination.md -- https://www.jqwidgets.com/react/react-grid/#https://www.jqwidgets.com/react/react-grid/react-grid-paging.htm -- https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/RecordPaging/React/Light/ -- http://tabulator.info/docs/4.5/page +By default, pagination works on the client-side. +To switch it to server-side, set `paginationMode="server"`. +You also need to set the `rowCount` prop to so the grid know the total number of pages. +Finally, you need to handle the `onPageChange` callback to load the rows for the corresponding page. + +{{"demo": "pages/components/data-grid/pagination/ServerPaginationGrid.js"}} + +## apiRef + +We exposed a set of methods that will let you achieve all the above features using the imperative apiRef. + +> ⚠️ Only use this API when you have no alternatives. Always start from the declarative APIs the Grid exposes. + +Below is an example on how you can reset the page using the imperative `setPage` method. + +{{"demo": "pages/components/data-grid/pagination/ApiRefPaginationGrid.js"}} diff --git a/packages/grid/data-grid/src/DataGrid.tsx b/packages/grid/data-grid/src/DataGrid.tsx index f993d653c84e6..93c38ff3f4c9d 100644 --- a/packages/grid/data-grid/src/DataGrid.tsx +++ b/packages/grid/data-grid/src/DataGrid.tsx @@ -11,7 +11,6 @@ const FORCED_PROPS: Partial = { export type DataGridProps = Omit< GridComponentProps, - | 'apiRef' | 'disableMultipleColumnsSorting' | 'disableMultipleSelection' | 'licenseStatus' diff --git a/packages/grid/x-grid-data-generator/src/useDemoData.ts b/packages/grid/x-grid-data-generator/src/useDemoData.ts index 292f192b68aaf..af198c696d8f7 100644 --- a/packages/grid/x-grid-data-generator/src/useDemoData.ts +++ b/packages/grid/x-grid-data-generator/src/useDemoData.ts @@ -8,7 +8,8 @@ export type DemoDataReturnType = { setRowLength: (count: number) => void; loadNewData: () => void; }; -export type DataSet = 'Commodity' | 'Employee'; + +type DataSet = 'Commodity' | 'Employee'; interface DemoDataOptions { dataSet: DataSet; diff --git a/packages/storybook/src/documentation/pages/demos/pagination/autoPageSize.demo.tsx b/packages/storybook/src/documentation/pages/demos/pagination/autoPageSize.demo.tsx deleted file mode 100644 index 3064fa9743f33..0000000000000 --- a/packages/storybook/src/documentation/pages/demos/pagination/autoPageSize.demo.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import * as React from 'react'; -import { Columns, RowsProp, XGrid } from '@material-ui/x-grid'; -import { randomCreatedDate, randomUpdatedDate } from '@material-ui/x-grid-data-generator'; -import '../demo.css'; - -export default function AutoPageSizeDemo() { - const columns: Columns = [ - { field: 'id', hide: true }, - { field: 'name', type: 'string' }, - { field: 'age', type: 'number' }, - { field: 'dateCreated', type: 'date', width: 180 }, - { field: 'lastLogin', type: 'dateTime', width: 180 }, - ]; - - const rows: RowsProp = [ - { - id: 1, - name: 'Damien', - age: 25, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 2, - name: 'Nicolas', - age: 36, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 3, - name: 'Kate', - age: 19, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 4, - name: 'Sebastien', - age: 28, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 5, - name: 'Louise', - age: 23, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 6, - name: 'George', - age: 10, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 7, - name: 'Anna', - age: 31, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 8, - name: 'Kim', - age: 20, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 9, - name: 'Paul', - age: 29, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 10, - name: 'Jack', - age: 25, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - ]; - - return ( -
- -
- ); -} diff --git a/packages/storybook/src/documentation/pages/demos/pagination/customPagination.demo.tsx b/packages/storybook/src/documentation/pages/demos/pagination/customPagination.demo.tsx deleted file mode 100644 index 00a9e3c9a80f1..0000000000000 --- a/packages/storybook/src/documentation/pages/demos/pagination/customPagination.demo.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import * as React from 'react'; -import { Columns, RowsProp, XGrid } from '@material-ui/x-grid'; -import { randomCreatedDate, randomUpdatedDate } from '@material-ui/x-grid-data-generator'; -import '../demo.css'; -import Pagination from '@material-ui/lab/Pagination'; - -function CustomPagination({ paginationProps }) { - return ( - paginationProps.setPage(value)} - /> - ); -} - -export default function CustomPaginationDemo() { - const columns: Columns = [ - { field: 'id', hide: true }, - { field: 'name', type: 'string' }, - { field: 'age', type: 'number' }, - { field: 'dateCreated', type: 'date', width: 180 }, - { field: 'lastLogin', type: 'dateTime', width: 180 }, - ]; - - const rows: RowsProp = [ - { - id: 1, - name: 'Damien', - age: 25, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 2, - name: 'Nicolas', - age: 36, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 3, - name: 'Kate', - age: 19, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 4, - name: 'Sebastien', - age: 28, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 5, - name: 'Louise', - age: 23, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 6, - name: 'George', - age: 10, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 7, - name: 'Anna', - age: 31, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 8, - name: 'Kim', - age: 20, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 9, - name: 'Paul', - age: 29, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 10, - name: 'Jack', - age: 25, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - ]; - - return ( - - ); -} diff --git a/packages/storybook/src/documentation/pages/demos/pagination/serverPagination.demo.tsx b/packages/storybook/src/documentation/pages/demos/pagination/serverPagination.demo.tsx deleted file mode 100644 index 0a53248667c90..0000000000000 --- a/packages/storybook/src/documentation/pages/demos/pagination/serverPagination.demo.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import * as React from 'react'; -import { Columns, PageChangeParams, RowsProp, XGrid } from '@material-ui/x-grid'; -import { - randomCreatedDate, - randomEmail, - randomId, - randomInt, - randomTraderName, - randomUpdatedDate, -} from '@material-ui/x-grid-data-generator'; - -function newRow() { - return { - id: randomId(), - name: randomTraderName(), - email: randomEmail(), - age: randomInt(10, 100), - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }; -} - -const columns: Columns = [ - { field: 'id', hide: true }, - { field: 'name', type: 'string' }, - { field: 'email', type: 'string' }, - { field: 'age', type: 'number' }, - { field: 'dateCreated', type: 'date', width: 180 }, - { field: 'lastLogin', type: 'dateTime', width: 180 }, -]; - -function loadServerRows(params: PageChangeParams): Promise { - return new Promise((resolve) => { - const rows: any[] = []; - while (rows.length < params.pageSize) { - rows.push(newRow()); - } - - setTimeout(() => { - resolve({ response: { rows }, request: { params } }); - }, 800); - }); -} - -export default function ServerPaginationDemo() { - const [rows, setRows] = React.useState([]); - const [loading, setLoading] = React.useState(false); - const currentPage = React.useRef(1); - - const onPageChange = (params) => { - currentPage.current = params.page; - setLoading(true); - loadServerRows(params).then(({ response, request }) => { - if (currentPage.current === request.params.page) { - setRows(response.rows); - setLoading(false); - } - }); - }; - - return ( - - ); -} diff --git a/packages/storybook/src/documentation/pages/demos/pagination/setPage.demo.tsx b/packages/storybook/src/documentation/pages/demos/pagination/setPage.demo.tsx deleted file mode 100644 index 20400d2ddaa67..0000000000000 --- a/packages/storybook/src/documentation/pages/demos/pagination/setPage.demo.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import * as React from 'react'; -import { Columns, RowsProp, XGrid, useApiRef } from '@material-ui/x-grid'; -import { randomCreatedDate, randomUpdatedDate } from '@material-ui/x-grid-data-generator'; -import '../demo.css'; - -export default function SetPageDemo() { - const apiRef = useApiRef(); - - React.useEffect(() => { - apiRef.current.setPage(2); - }, [apiRef]); - - const columns: Columns = [ - { field: 'id', hide: true }, - { field: 'name', type: 'string' }, - { field: 'age', type: 'number' }, - { field: 'dateCreated', type: 'date', width: 180 }, - { field: 'lastLogin', type: 'dateTime', width: 180 }, - ]; - - const rows: RowsProp = [ - { - id: 1, - name: 'Damien', - age: 25, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 2, - name: 'Nicolas', - age: 36, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 3, - name: 'Kate', - age: 19, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 4, - name: 'Sebastien', - age: 28, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 5, - name: 'Louise', - age: 23, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 6, - name: 'George', - age: 10, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 7, - name: 'Anna', - age: 31, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 8, - name: 'Kim', - age: 20, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 9, - name: 'Paul', - age: 29, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 10, - name: 'Jack', - age: 25, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - ]; - - return ( - - ); -} diff --git a/packages/storybook/src/documentation/pages/demos/pagination/simplePagination.demo.tsx b/packages/storybook/src/documentation/pages/demos/pagination/simplePagination.demo.tsx deleted file mode 100644 index b5335c0a6e50e..0000000000000 --- a/packages/storybook/src/documentation/pages/demos/pagination/simplePagination.demo.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import * as React from 'react'; -import { Columns, RowsProp, XGrid } from '@material-ui/x-grid'; -import { randomCreatedDate, randomUpdatedDate } from '@material-ui/x-grid-data-generator'; -import '../demo.css'; - -export default function SimplePaginationDemo() { - const columns: Columns = [ - { field: 'id', hide: true }, - { field: 'name', type: 'string' }, - { field: 'age', type: 'number' }, - { field: 'dateCreated', type: 'date', width: 180 }, - { field: 'lastLogin', type: 'dateTime', width: 180 }, - ]; - - const rows: RowsProp = [ - { - id: 1, - name: 'Damien', - age: 25, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 2, - name: 'Nicolas', - age: 36, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 3, - name: 'Kate', - age: 19, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 4, - name: 'Sebastien', - age: 28, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 5, - name: 'Louise', - age: 23, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 6, - name: 'George', - age: 10, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 7, - name: 'Anna', - age: 31, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 8, - name: 'Kim', - age: 20, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 9, - name: 'Paul', - age: 29, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - { - id: 10, - name: 'Jack', - age: 25, - dateCreated: randomCreatedDate(), - lastLogin: randomUpdatedDate(), - }, - ]; - - return ( - - ); -} diff --git a/packages/storybook/src/documentation/pages/pagination.stories.mdx b/packages/storybook/src/documentation/pages/pagination.stories.mdx deleted file mode 100644 index 28415c7fe8bda..0000000000000 --- a/packages/storybook/src/documentation/pages/pagination.stories.mdx +++ /dev/null @@ -1,159 +0,0 @@ -import { XGrid } from '@material-ui/x-grid'; -import SimplePaginationDemo from './demos/pagination/simplePagination.demo'; -import AutoPageSizeDemo from './demos/pagination/autoPageSize.demo'; -import SetPageDemo from './demos/pagination/setPage.demo'; -import CustomPaginationDemo from './demos/pagination/customPagination.demo'; -import ServerPaginationDemo from './demos/pagination/serverPagination.demo'; - - - -# Pagination - -- **Switch pagination** - -By Default, XGrid uses infinite rows and virtualization. However, we also implemented pagination if you wish to limit the number of rows visible in the grid. -To turn it on, toggle the `pagination` boolean property of the `options` React prop as below. - -```tsx - -``` - -- **Set page size** - -Our default `pageSize` is set to `100`. You can change this value by setting the `pageSize` property of the `options` React prop as below. - -```tsx - -``` - -- **Set Rows per page options** - -Along with the `pageSize` property, we added the `rowsPerPageOptions` that let you select the `pageSize` dynamically using XGrid UI. -The default `rowsPerPageOptions` is set to `[25, 50, 100]`. You can change this value by setting the `rowsPerPageOptions` property of the `options` prop as below. - -```tsx - -``` - -Please find below an example of a grid with pagination using the options prop described above. - - - -- ** Set the current page** - -Finally, we exposed the `page` property, which let you select the current page rendered by XGrid. Default value is 1. -If you would like to render the second page, then you can set this property to `2` as below - -```tsx - -``` - -## Auto pagination - -The property `autoPageSize` is available as an option to auto-scale the `pageSize` with the container size to the max number of rows to avoid rendering a vertical scroll bar. -By default, this feature is off and can be turned on, by toggling the `autoPageSize` boolean property of the `options` React prop as below. - -```tsx - -``` - -Please find below an example of grid with `autoPageSize` turned on as described above. - - - -## Overriding the Pagination component - -Our default pagination component is our Material-UI `TablePagination` available [here](https://material-ui.com/api/table-pagination/). -Along with others, you can override this component and replace it with our Pagination from our lab [here](https://material-ui.com/components/pagination/) -or use your own pagination. -To achieve this, just set the pagination property of the `components` react prop as below. - -```tsx - -``` - - - -## Server-side pagination - -XGrid supports both client and server-side pagination. By default, pagination works on the client-side. To switch it to server-side, -set the property `paginationMode` to `server`. -**Note**: You also need to set the `rowCount` property to override the number of rows in the grid so XGrid can calculate the total number of pages. - -Finally, you're going to need to handle the `onPageChange` event, to load the rows for the corresponding page. - -```tsx -const [rows, setRows] = React.useState([]); -const onPageChange = (params) => { - loadServerRows(params).then((newRows) => { - setRows(newRows); - }); -}; - -; -``` - - - -### Pagination API - -We exposed a set of methods that will let you achieve all the above features using the `ApiRef` object. More info on our API page [here](??). - -Below is an example on how you can reset the page using the `setPage` method of the API. - -```tsx -const apiRef = useApiRef(); - -React.useEffect(() => { - apiRef.current?.setPage(2); -}, [apiRef]); - -return ( - -); -``` - -