From abf88f08909eea4fa173c435f9f6c646605b23d7 Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 7 Jul 2021 18:29:05 +0200 Subject: [PATCH 1/5] implement control state for sorting --- .../data-grid/sorting/ServerSortingGrid.js | 6 +- .../data-grid/sorting/ServerSortingGrid.tsx | 7 +- .../hooks/features/sorting/useGridSorting.ts | 46 +++---- .../_modules_/grid/models/gridOptions.tsx | 5 +- .../x-grid/src/tests/sorting.XGrid.test.tsx | 102 +++++++++++---- .../src/stories/grid-sorting.stories.tsx | 118 ++++++++++++++++-- 6 files changed, 220 insertions(+), 64 deletions(-) diff --git a/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.js b/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.js index caf9017e063b2..293e4c21fb312 100644 --- a/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.js +++ b/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.js @@ -39,10 +39,8 @@ export default function ServerSortingGrid() { const [rows, setRows] = React.useState([]); const [loading, setLoading] = React.useState(false); - const handleSortModelChange = (params) => { - if (params.sortModel !== sortModel) { - setSortModel(params.sortModel); - } + const handleSortModelChange = (newModel) => { + setSortModel(newModel); }; React.useEffect(() => { diff --git a/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.tsx b/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.tsx index cef096f850ac1..bfe3db7afc809 100644 --- a/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.tsx +++ b/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.tsx @@ -3,7 +3,6 @@ import { GridRowsProp, DataGrid, GridSortModel, - GridSortModelParams, } from '@material-ui/data-grid'; import { useDemoData, GridData } from '@material-ui/x-grid-data-generator'; @@ -42,10 +41,8 @@ export default function ServerSortingGrid() { const [rows, setRows] = React.useState([]); const [loading, setLoading] = React.useState(false); - const handleSortModelChange = (params: GridSortModelParams) => { - if (params.sortModel !== sortModel) { - setSortModel(params.sortModel); - } + const handleSortModelChange = (newModel: GridSortModel) => { + setSortModel(newModel); }; React.useEffect(() => { diff --git a/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts b/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts index 6971fda635de3..c06c24be57f56 100644 --- a/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts +++ b/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts @@ -8,14 +8,14 @@ import { GRID_ROWS_UPDATE, GRID_SORT_MODEL_CHANGE, } from '../../../constants/eventsConstants'; +import { GridComponentProps } from '../../../GridComponentProps'; import { GridApiRef } from '../../../models/api/gridApiRef'; import { GridSortApi } from '../../../models/api/gridSortApi'; import { GridCellValue } from '../../../models/gridCell'; import { GridColDef } from '../../../models/colDef/gridColDef'; import { GridFeatureModeConstant } from '../../../models/gridFeatureMode'; import { GridColumnHeaderParams } from '../../../models/params/gridColumnHeaderParams'; -import { GridSortModelParams } from '../../../models/params/gridSortModelParams'; -import { GridRowId, GridRowModel, GridRowsProp } from '../../../models/gridRows'; +import { GridRowId, GridRowModel } from '../../../models/gridRows'; import { GridFieldComparatorList, GridSortItem, @@ -26,7 +26,7 @@ import { import { isDesc, nextGridSortDirection } from '../../../utils/sortingUtils'; import { isEnterKey } from '../../../utils/keyboardUtils'; import { isDeepEqual } from '../../../utils/utils'; -import { useGridApiEventHandler, useGridApiOptionHandler } from '../../root/useGridApiEventHandler'; +import { useGridApiEventHandler } from '../../root/useGridApiEventHandler'; import { useGridApiMethod } from '../../root/useGridApiMethod'; import { optionsSelector } from '../../utils/optionsSelector'; import { useLogger } from '../../utils/useLogger'; @@ -36,7 +36,10 @@ import { useGridState } from '../core/useGridState'; import { gridRowCountSelector } from '../rows/gridRowsSelector'; import { sortedGridRowIdsSelector, sortedGridRowsSelector } from './gridSortingSelector'; -export const useGridSorting = (apiRef: GridApiRef, { rows }: { rows: GridRowsProp }) => { +export const useGridSorting = ( + apiRef: GridApiRef, + props: Pick, +) => { const logger = useLogger('useGridSorting'); const [gridState, setGridState, forceUpdate] = useGridState(apiRef); @@ -44,15 +47,6 @@ export const useGridSorting = (apiRef: GridApiRef, { rows }: { rows: GridRowsPro const visibleColumns = useGridSelector(apiRef, visibleGridColumnsSelector); const rowCount = useGridSelector(apiRef, gridRowCountSelector); - const getSortModelParams = React.useCallback( - (sortModel: GridSortModel): GridSortModelParams => ({ - sortModel, - api: apiRef.current, - columns: apiRef.current.getAllColumns(), - }), - [apiRef], - ); - const upsertSortModel = React.useCallback( (field: string, sortItem?: GridSortItem): GridSortModel => { const existingIdx = gridState.sorting.sortModel.findIndex((c) => c.field === field); @@ -211,10 +205,9 @@ export const useGridSorting = (apiRef: GridApiRef, { rows }: { rows: GridRowsPro if (visibleColumns.length === 0) { return; } - apiRef.current.publishEvent(GRID_SORT_MODEL_CHANGE, getSortModelParams(sortModel)); apiRef.current.applySorting(); }, - [setGridState, forceUpdate, visibleColumns.length, apiRef, getSortModelParams], + [setGridState, forceUpdate, visibleColumns.length, apiRef], ); const sortColumn = React.useCallback( @@ -300,8 +293,6 @@ export const useGridSorting = (apiRef: GridApiRef, { rows }: { rows: GridRowsPro useGridApiEventHandler(apiRef, GRID_ROWS_UPDATE, apiRef.current.applySorting); useGridApiEventHandler(apiRef, GRID_COLUMNS_CHANGE, onColUpdated); - useGridApiOptionHandler(apiRef, GRID_SORT_MODEL_CHANGE, options.onSortModelChange); - const sortApi: GridSortApi = { getSortModel, getSortedRows, @@ -315,7 +306,7 @@ export const useGridSorting = (apiRef: GridApiRef, { rows }: { rows: GridRowsPro React.useEffect(() => { // When the rows prop change, we re apply the sorting. apiRef.current.applySorting(); - }, [apiRef, rows]); + }, [apiRef, props.rows]); React.useEffect(() => { if (rowCount > 0) { @@ -325,11 +316,24 @@ export const useGridSorting = (apiRef: GridApiRef, { rows }: { rows: GridRowsPro }, [rowCount, apiRef, logger]); React.useEffect(() => { - const sortModel = options.sortModel || []; + apiRef.current.updateControlState({ + stateId: 'sortModel', + propModel: props.sortModel, + propOnChange: props.onSortModelChange, + stateSelector: (state) => state.sorting.sortModel, + onChangeCallback: (model) => { + apiRef.current.publishEvent(GRID_SORT_MODEL_CHANGE, model); + }, + }); + }, [apiRef, props.sortModel, props.onSortModelChange]); + + React.useEffect(() => { + const sortModel = props.sortModel || []; const oldSortModel = apiRef.current.state.sorting.sortModel; if (!isDeepEqual(sortModel, oldSortModel)) { + setGridState((state) => ({ ...state, sorting: { ...state.sorting, sortModel } })); // we use apiRef to avoid watching setSortModel as it will trigger an update on every state change - apiRef.current.setSortModel(sortModel); + apiRef.current.applySorting(); } - }, [options.sortModel, apiRef]); + }, [props.sortModel, apiRef, setGridState]); }; diff --git a/packages/grid/_modules_/grid/models/gridOptions.tsx b/packages/grid/_modules_/grid/models/gridOptions.tsx index c199f43f45d0b..4dcd73ce52151 100644 --- a/packages/grid/_modules_/grid/models/gridOptions.tsx +++ b/packages/grid/_modules_/grid/models/gridOptions.tsx @@ -14,7 +14,6 @@ import { GridColumnHeaderParams } from './params/gridColumnHeaderParams'; import { GridFilterModelParams } from './params/gridFilterModelParams'; import { GridPageChangeParams } from './params/gridPageChangeParams'; import { GridRowParams } from './params/gridRowParams'; -import { GridSortModelParams } from './params/gridSortModelParams'; import { GridSelectionModel } from './gridSelectionModel'; import { GridSortDirection, GridSortModel } from './gridSortModel'; import { @@ -418,9 +417,9 @@ export interface GridOptions { onSelectionModelChange?: (selectionModel: GridRowId[]) => void; /** * Callback fired when the sort model changes before a column is sorted. - * @param param With all properties from [[GridSortModelParams]]. + * @param param With all properties from [[GridSortModel]]. */ - onSortModelChange?: (params: GridSortModelParams) => void; + onSortModelChange?: (model: GridSortModel) => void; /** * Callback fired when the state of the grid is updated. */ diff --git a/packages/grid/x-grid/src/tests/sorting.XGrid.test.tsx b/packages/grid/x-grid/src/tests/sorting.XGrid.test.tsx index 1a6b12ef39296..3ea87712d4eda 100644 --- a/packages/grid/x-grid/src/tests/sorting.XGrid.test.tsx +++ b/packages/grid/x-grid/src/tests/sorting.XGrid.test.tsx @@ -1,8 +1,13 @@ import * as React from 'react'; -import { GridApiRef, GridSortModel, useGridApiRef } from '@material-ui/data-grid'; +import { + GridApiRef, + GridComponentProps, + GridSortModel, + useGridApiRef, +} from '@material-ui/data-grid'; import { XGrid } from '@material-ui/x-grid'; import { expect } from 'chai'; -import { useFakeTimers } from 'sinon'; +import { spy, useFakeTimers } from 'sinon'; import { getColumnValues, getCell, getColumnHeaderCell } from 'test/utils/helperFn'; import { createClientRenderStrictMode, @@ -54,21 +59,16 @@ describe(' - Sorting', () => { let apiRef: GridApiRef; - const TestCase = (props: { - rows?: any[]; - sortModel: GridSortModel; - disableMultipleColumnsSorting?: boolean; - }) => { - const { sortModel, rows, disableMultipleColumnsSorting } = props; + const TestCase = (props: Partial) => { + const { rows, ...other } = props; apiRef = useGridApiRef(); return (
); @@ -115,7 +115,8 @@ describe(' - Sorting', () => { }); it('should allow apiRef to setSortModel', () => { - renderBrandSortedAsc(); + render(); + apiRef.current.setSortModel([{ field: 'brand', sort: 'desc' }]); expect(getColumnValues()).to.deep.equal(['Puma', 'Nike', 'Adidas']); }); @@ -130,8 +131,8 @@ describe(' - Sorting', () => { }); it('should allow to set multiple Sort items via apiRef', () => { - renderBrandSortedAsc(); - expect(getColumnValues()).to.deep.equal(['Adidas', 'Nike', 'Puma']); + render(); + const sortModel: GridSortModel = [ { field: 'year', sort: 'desc' }, { field: 'brand', sort: 'asc' }, @@ -144,7 +145,8 @@ describe(' - Sorting', () => { describe('multi-sorting', () => { ['shiftKey', 'metaKey', 'ctrlKey'].forEach((key) => { it(`should do a multi-sorting when clicking the header cell while ${key} is pressed`, () => { - render(); + render(); + apiRef.current.setSortModel([{ field: 'year', sort: 'desc' }]); expect(getColumnValues()).to.deep.equal(['Puma', 'Nike', 'Adidas']); fireEvent.click(getColumnHeaderCell(0), { [key]: true }); expect(getColumnValues()).to.deep.equal(['Puma', 'Adidas', 'Nike']); @@ -153,7 +155,8 @@ describe(' - Sorting', () => { ['metaKey', 'ctrlKey'].forEach((key) => { it(`should do nothing when pressing Enter while ${key} is pressed`, () => { - render(); + render(); + apiRef.current.setSortModel([{ field: 'year', sort: 'desc' }]); expect(getColumnValues()).to.deep.equal(['Puma', 'Nike', 'Adidas']); getColumnHeaderCell(1).focus(); fireEvent.keyDown(getColumnHeaderCell(1), { key: 'Enter', [key]: true }); @@ -162,7 +165,8 @@ describe(' - Sorting', () => { }); it('should do a multi-sorting pressing Enter while shiftKey is pressed', () => { - render(); + render(); + apiRef.current.setSortModel([{ field: 'year', sort: 'desc' }]); expect(getColumnValues()).to.deep.equal(['Puma', 'Nike', 'Adidas']); getColumnHeaderCell(0).focus(); fireEvent.keyDown(getColumnHeaderCell(0), { key: 'Enter', shiftKey: true }); @@ -170,16 +174,16 @@ describe(' - Sorting', () => { }); it(`should not do a multi-sorting if no multiple key is pressed`, () => { - render(); + render(); + apiRef.current.setSortModel([{ field: 'year', sort: 'desc' }]); expect(getColumnValues()).to.deep.equal(['Puma', 'Nike', 'Adidas']); fireEvent.click(getColumnHeaderCell(0)); expect(getColumnValues()).to.deep.equal(['Adidas', 'Nike', 'Puma']); }); it('should not do a multi-sorting if disableMultipleColumnsSorting is true', () => { - render( - , - ); + render(); + apiRef.current.setSortModel([{ field: 'year', sort: 'desc' }]); expect(getColumnValues()).to.deep.equal(['Puma', 'Nike', 'Adidas']); fireEvent.click(getColumnHeaderCell(0), { shiftKey: true }); expect(getColumnValues()).to.deep.equal(['Adidas', 'Nike', 'Puma']); @@ -264,4 +268,60 @@ describe(' - Sorting', () => { setProps({ extra: true }); expect(renderCellCount).to.equal(2); }); + + describe('control Sorting', () => { + it('should update the sorting state when neither the model nor the onChange are set', () => { + render(); + expect(getColumnValues()).to.deep.equal(['Nike', 'Adidas', 'Puma']); + fireEvent.click(getColumnHeaderCell(0)); + expect(getColumnValues()).to.deep.equal(['Adidas', 'Nike', 'Puma']); + }); + + it('should not update the sort model when the sortModelProp is set', () => { + const testSortModel: GridSortModel = [{ field: 'brand', sort: 'desc' }]; + render(); + expect(getColumnValues()).to.deep.equal(['Puma', 'Nike', 'Adidas']); + fireEvent.click(getColumnHeaderCell(0)); + expect(getColumnValues()).to.deep.equal(['Puma', 'Nike', 'Adidas']); + }); + + it('should update the sort state when the model is not set, but the onChange is set', () => { + const onModelChange = spy(); + render(); + expect(onModelChange.callCount).to.equal(0); + fireEvent.click(getColumnHeaderCell(0)); + expect(onModelChange.callCount).to.equal(1); + expect(onModelChange.lastCall.firstArg).to.deep.equal([{ field: 'brand', sort: 'asc' }]); + }); + + it('should control sort state when the model and the onChange are set', () => { + let expectedModel: GridSortModel = []; + const ControlCase = (props: Partial) => { + const { rows, columns, ...others } = props; + const [caseSortModel, setSortModel] = React.useState([]); + const handleSortChange = (newModel) => { + setSortModel(newModel); + expectedModel = newModel; + }; + + return ( +
+ +
+ ); + }; + + render(); + fireEvent.click(getColumnHeaderCell(0)); + expect(getColumnValues()).to.deep.equal(['Adidas', 'Nike', 'Puma']); + expect(expectedModel).to.deep.equal([{ field: 'brand', sort: 'asc' }]); + }); + }); }); diff --git a/packages/storybook/src/stories/grid-sorting.stories.tsx b/packages/storybook/src/stories/grid-sorting.stories.tsx index 81b1823c03ad1..e2c50cca83bc0 100644 --- a/packages/storybook/src/stories/grid-sorting.stories.tsx +++ b/packages/storybook/src/stories/grid-sorting.stories.tsx @@ -5,9 +5,9 @@ import { GridColDef, XGrid, GridRowsProp, - GridSortModelParams, GridSortModel, useGridApiRef, + getInitialGridSortingState, } from '@material-ui/x-grid'; import { action } from '@storybook/addon-actions'; @@ -426,21 +426,25 @@ export const SortedEventsOptions = () => { ); }; -function sortServerRows(rows: Readonly, params: GridSortModelParams): Promise { +function sortServerRows( + rows: Readonly, + sortModel: GridSortModel, + columns: GridColDef[], +): Promise { return new Promise((resolve) => { setTimeout(() => { - if (params.sortModel.length === 0) { + if (sortModel.length === 0) { resolve(getRows()); return; } - const sortedCol = params.sortModel[0]; - const comparator = params.columns[0].sortComparator!; + const sortedCol = sortModel[0]; + const comparator = columns[0].sortComparator!; const clonedRows = [...rows]; let sortedRows = clonedRows.sort((a, b) => comparator(a[sortedCol.field], b[sortedCol.field], a, b), ); - if (params.sortModel[0].sort === 'desc') { + if (sortModel[0].sort === 'desc') { sortedRows = sortedRows.reverse(); } @@ -455,15 +459,15 @@ export const ServerSideSorting = () => { const [loading, setLoading] = React.useState(false); const onSortModelChange = React.useCallback( - async (params: GridSortModelParams) => { + async (model: GridSortModel) => { setLoading(true); - action('onSortModelChange')(params); + action('onSortModelChange')(model); - const newRows = await sortServerRows(rows, params); + const newRows = await sortServerRows(rows, model, columns); setRows(newRows); setLoading(false); }, - [rows], + [columns, rows], ); // We use `useMemo` here, to keep the same ref and not trigger another sort on the next rendering @@ -527,3 +531,97 @@ export const OriginalOrder = () => { ); }; + +export function SimpleModelWithOnChangeControlSort() { + const [simpleColumns] = React.useState([ + { + field: 'id', + }, + { field: 'name' }, + ]); + const [simpleRows] = React.useState([ + { + id: '1', + name: 'Paris', + }, + { + id: '2', + name: 'Nice', + }, + { + id: '3', + name: 'London', + }, + ]); + + const [simpleSortModel, setSortModel] = React.useState( + getInitialGridSortingState().sortModel, + ); + const handleSortChange = React.useCallback((model) => { + setSortModel(model); + }, []); + + return ( + + ); +} +export function SimpleModelControlSort() { + const [simpleColumns] = React.useState([ + { + field: 'id', + }, + { field: 'name' }, + ]); + const [simpleRows] = React.useState([ + { + id: '1', + name: 'Paris', + }, + { + id: '2', + name: 'Nice', + }, + { + id: '3', + name: 'London', + }, + ]); + + const [simpleSortModel] = React.useState([{ field: 'name', sort: 'desc' }]); + + return ; +} +export function SimpleOnChangeControlSort() { + const [simpleColumns] = React.useState([ + { + field: 'id', + }, + { field: 'name' }, + ]); + const [simpleRows] = React.useState([ + { + id: '1', + name: 'Paris', + }, + { + id: '2', + name: 'Nice', + }, + { + id: '3', + name: 'London', + }, + ]); + + const handleSortChange = React.useCallback((model) => { + // eslint-disable-next-line no-console + console.log('Sort model changed to', model); + }, []); + + return ; +} From 135d8d1245f3758285727f01d78c3fde3dd9929e Mon Sep 17 00:00:00 2001 From: damien Date: Thu, 8 Jul 2021 11:44:54 +0200 Subject: [PATCH 2/5] prettier --- .../components/data-grid/sorting/ServerSortingGrid.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.tsx b/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.tsx index bfe3db7afc809..3a2eea237e057 100644 --- a/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.tsx +++ b/docs/src/pages/components/data-grid/sorting/ServerSortingGrid.tsx @@ -1,9 +1,5 @@ import * as React from 'react'; -import { - GridRowsProp, - DataGrid, - GridSortModel, -} from '@material-ui/data-grid'; +import { GridRowsProp, DataGrid, GridSortModel } from '@material-ui/data-grid'; import { useDemoData, GridData } from '@material-ui/x-grid-data-generator'; function loadServerRows(sortModel: GridSortModel, data: GridData): Promise { From a6a4fd6c22381375378bdd13cc2fda992d7d3500 Mon Sep 17 00:00:00 2001 From: damien Date: Thu, 15 Jul 2021 14:40:05 +0200 Subject: [PATCH 3/5] fix demos --- docs/pages/api-docs/data-grid/data-grid.md | 2 +- docs/pages/api-docs/data-grid/x-grid.md | 2 +- .../data-grid/sorting/BasicSortingGrid.js | 15 ++++++----- .../data-grid/sorting/BasicSortingGrid.tsx | 17 +++++++----- .../sorting/ComparatorSortingGrid.js | 21 +++++++++------ .../sorting/ComparatorSortingGrid.tsx | 21 +++++++++------ .../data-grid/sorting/MultiSortingGrid.js | 23 +++++++++------- .../data-grid/sorting/MultiSortingGrid.tsx | 25 +++++++++-------- .../data-grid/sorting/OrderSortingGrid.js | 15 ++++++----- .../data-grid/sorting/OrderSortingGrid.tsx | 17 +++++++----- .../x-grid-data-generator/src/useDemoData.ts | 27 +++++++++++-------- 11 files changed, 109 insertions(+), 76 deletions(-) diff --git a/docs/pages/api-docs/data-grid/data-grid.md b/docs/pages/api-docs/data-grid/data-grid.md index 302382efbf16b..42f72fb25bf6f 100644 --- a/docs/pages/api-docs/data-grid/data-grid.md +++ b/docs/pages/api-docs/data-grid/data-grid.md @@ -83,7 +83,7 @@ import { DataGrid } from '@material-ui/data-grid'; | onRowEnter | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse enter comes from a row container element. | | onRowLeave | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a row container element. | | onSelectionModelChange | (param: GridSelectionModelChangeParams) => void | | Callback fired when the selection state of one or multiple rows changes. | -| onSortModelChange | (param: GridSortModelParams) => void | | Callback fired when the sort model changes before a column is sorted. | +| onSortModelChange | (model: GridSortModel) => void | | Callback fired when the sort model changes before a column is sorted. | | page | number | 1 | Set the current page. | | pageSize | number | 100 | Set the number of rows in one page. | | paginationMode | GridFeatureMode | 'client' | Pagination can be processed on the server or client-side. Set it to 'client' if you would like to handle the pagination on the client-side. Set it to 'server' if you would like to handle the pagination on the server-side. | diff --git a/docs/pages/api-docs/data-grid/x-grid.md b/docs/pages/api-docs/data-grid/x-grid.md index d701450049cb5..0317963bd6494 100644 --- a/docs/pages/api-docs/data-grid/x-grid.md +++ b/docs/pages/api-docs/data-grid/x-grid.md @@ -89,7 +89,7 @@ import { XGrid } from '@material-ui/x-grid'; | onRowLeave | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a row container element. | | onRowsScrollEnd | (param: GridRowScrollEndParams) => void | | Callback fired when scrolling to the bottom of the grid viewport. | | onSelectionModelChange | (param: GridSelectionModelChangeParams) => void | | Callback fired when the selection state of one or multiple rows changes. | -| onSortModelChange | (param: GridSortModelParams) => void | | Callback fired when the sort model changes before a column is sorted. | +| onSortModelChange | (model: GridSortModel) => void | | Callback fired when the sort model changes before a column is sorted. | | page | number | 1 | Set the current page. | | pageSize | number | 100 | Set the number of rows in one page. | | pagination | boolean | false | If `true`, pagination is enabled. | diff --git a/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.js b/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.js index ff7936aa170f5..082d5be6863d6 100644 --- a/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.js +++ b/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.js @@ -9,16 +9,19 @@ export default function BasicSortingGrid() { maxColumns: 6, }); + const [sortModel, setSortModel] = React.useState([ + { + field: 'commodity', + sort: 'asc', + }, + ]); + return (
setSortModel(model)} />
); diff --git a/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.tsx b/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.tsx index 66c899ceb32ac..42a6bee0a90a9 100644 --- a/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.tsx +++ b/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { DataGrid, GridSortDirection } from '@material-ui/data-grid'; +import { DataGrid, GridSortDirection, GridSortModel } from '@material-ui/data-grid'; import { useDemoData } from '@material-ui/x-grid-data-generator'; export default function BasicSortingGrid() { @@ -9,16 +9,19 @@ export default function BasicSortingGrid() { maxColumns: 6, }); + const [sortModel, setSortModel] = React.useState([ + { + field: 'commodity', + sort: 'asc' as GridSortDirection, + }, + ]); + return (
setSortModel(model)} />
); diff --git a/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.js b/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.js index eb36240339cc0..7c475ede25c13 100644 --- a/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.js +++ b/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.js @@ -68,17 +68,22 @@ const rows = [ }, ]; -const sortModel = [ - { - field: 'username', - sort: 'asc', - }, -]; - export default function ComparatorSortingGrid() { + const [sortModel, setSortModel] = React.useState([ + { + field: 'username', + sort: 'asc', + }, + ]); + return (
- + setSortModel(model)} + />
); } diff --git a/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.tsx b/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.tsx index ae0ad2891ad25..2d73d2439a5f2 100644 --- a/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.tsx +++ b/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.tsx @@ -5,6 +5,7 @@ import { DataGrid, GridSortDirection, GridValueGetterParams, + GridSortModel, } from '@material-ui/data-grid'; import { randomCreatedDate, @@ -74,17 +75,21 @@ const rows: GridRowsProp = [ }, ]; -const sortModel = [ - { - field: 'username', - sort: 'asc' as GridSortDirection, - }, -]; - export default function ComparatorSortingGrid() { + const [sortModel, setSortModel] = React.useState([ + { + field: 'username', + sort: 'asc' as GridSortDirection, + }, + ]); return (
- + setSortModel(model)} + />
); } diff --git a/docs/src/pages/components/data-grid/sorting/MultiSortingGrid.js b/docs/src/pages/components/data-grid/sorting/MultiSortingGrid.js index 281871a597d52..ac98378ce0ee4 100644 --- a/docs/src/pages/components/data-grid/sorting/MultiSortingGrid.js +++ b/docs/src/pages/components/data-grid/sorting/MultiSortingGrid.js @@ -9,20 +9,23 @@ export default function MultiSortingGrid() { maxColumns: 6, }); + const [sortModel, setSortModel] = React.useState([ + { + field: 'commodity', + sort: 'asc', + }, + { + field: 'desk', + sort: 'desc', + }, + ]); + return (
setSortModel(model)} />
); diff --git a/docs/src/pages/components/data-grid/sorting/MultiSortingGrid.tsx b/docs/src/pages/components/data-grid/sorting/MultiSortingGrid.tsx index 590d40040fc72..0dba4863a79e3 100644 --- a/docs/src/pages/components/data-grid/sorting/MultiSortingGrid.tsx +++ b/docs/src/pages/components/data-grid/sorting/MultiSortingGrid.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { XGrid, GridSortDirection } from '@material-ui/x-grid'; +import { XGrid, GridSortDirection, GridSortModel } from '@material-ui/x-grid'; import { useDemoData } from '@material-ui/x-grid-data-generator'; export default function MultiSortingGrid() { @@ -9,20 +9,23 @@ export default function MultiSortingGrid() { maxColumns: 6, }); + const [sortModel, setSortModel] = React.useState([ + { + field: 'commodity', + sort: 'asc' as GridSortDirection, + }, + { + field: 'desk', + sort: 'desc' as GridSortDirection, + }, + ]); + return (
setSortModel(model)} />
); diff --git a/docs/src/pages/components/data-grid/sorting/OrderSortingGrid.js b/docs/src/pages/components/data-grid/sorting/OrderSortingGrid.js index c826bb81f14f3..14a2bbe4520d3 100644 --- a/docs/src/pages/components/data-grid/sorting/OrderSortingGrid.js +++ b/docs/src/pages/components/data-grid/sorting/OrderSortingGrid.js @@ -9,16 +9,19 @@ export default function OrderSortingGrid() { maxColumns: 6, }); + const [sortModel, setSortModel] = React.useState([ + { + field: 'commodity', + sort: 'asc', + }, + ]); + return (
setSortModel(model)} {...data} />
diff --git a/docs/src/pages/components/data-grid/sorting/OrderSortingGrid.tsx b/docs/src/pages/components/data-grid/sorting/OrderSortingGrid.tsx index f1787f08c20d1..ae7f9cae87fe6 100644 --- a/docs/src/pages/components/data-grid/sorting/OrderSortingGrid.tsx +++ b/docs/src/pages/components/data-grid/sorting/OrderSortingGrid.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { DataGrid, GridSortDirection } from '@material-ui/data-grid'; +import { DataGrid, GridSortDirection, GridSortModel } from '@material-ui/data-grid'; import { useDemoData } from '@material-ui/x-grid-data-generator'; export default function OrderSortingGrid() { @@ -9,16 +9,19 @@ export default function OrderSortingGrid() { maxColumns: 6, }); + const [sortModel, setSortModel] = React.useState([ + { + field: 'commodity', + sort: 'asc' as GridSortDirection, + }, + ]); + return (
setSortModel(model)} {...data} />
diff --git a/packages/grid/x-grid-data-generator/src/useDemoData.ts b/packages/grid/x-grid-data-generator/src/useDemoData.ts index db5b8e0012007..be22bbcbd6ade 100644 --- a/packages/grid/x-grid-data-generator/src/useDemoData.ts +++ b/packages/grid/x-grid-data-generator/src/useDemoData.ts @@ -80,11 +80,24 @@ function deepFreeze(object) { } export const useDemoData = (options: DemoDataOptions): DemoDataReturnType => { - const [data, setData] = React.useState({ columns: [], rows: [] }); const [rowLength, setRowLength] = React.useState(options.rowLength); const [index, setIndex] = React.useState(0); const [loading, setLoading] = React.useState(true); + const getColumns = React.useCallback(()=> { + let columns = + options.dataSet === 'Commodity' + ? getCommodityColumns(options.editable) + : getEmployeeColumns(); + + if (options.maxColumns) { + columns = columns.slice(0, options.maxColumns); + } + return columns; + }, [options.dataSet, options.editable, options.maxColumns]); + + const [data, setData] = React.useState({ columns: getColumns(), rows: [] }); + React.useEffect(() => { const cacheKey = `${options.dataSet}-${rowLength}-${index}-${options.maxColumns}`; @@ -101,17 +114,9 @@ export const useDemoData = (options: DemoDataOptions): DemoDataReturnType => { (async () => { setLoading(true); - let columns = - options.dataSet === 'Commodity' - ? getCommodityColumns(options.editable) - : getEmployeeColumns(); - - if (options.maxColumns) { - columns = columns.slice(0, options.maxColumns); - } let newData; - + const columns = getColumns(); if (rowLength > 1000) { newData = await getRealData(1000, columns); newData = await extrapolateSeed(rowLength, columns, newData); @@ -136,7 +141,7 @@ export const useDemoData = (options: DemoDataOptions): DemoDataReturnType => { return () => { active = false; }; - }, [rowLength, options.dataSet, index, options.maxColumns, options.editable]); + }, [rowLength, data.columns, options.dataSet, options.maxColumns, index, getColumns]); return { data, From f731c10f75c18be8ebe6e5c771cef191281fb2ef Mon Sep 17 00:00:00 2001 From: damien Date: Thu, 15 Jul 2021 15:00:33 +0200 Subject: [PATCH 4/5] prettier --- packages/grid/x-grid-data-generator/src/useDemoData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/grid/x-grid-data-generator/src/useDemoData.ts b/packages/grid/x-grid-data-generator/src/useDemoData.ts index be22bbcbd6ade..3889a1b56f659 100644 --- a/packages/grid/x-grid-data-generator/src/useDemoData.ts +++ b/packages/grid/x-grid-data-generator/src/useDemoData.ts @@ -84,7 +84,7 @@ export const useDemoData = (options: DemoDataOptions): DemoDataReturnType => { const [index, setIndex] = React.useState(0); const [loading, setLoading] = React.useState(true); - const getColumns = React.useCallback(()=> { + const getColumns = React.useCallback(() => { let columns = options.dataSet === 'Commodity' ? getCommodityColumns(options.editable) From f8deee0f889f8174a19d673afe8f3195f03718f8 Mon Sep 17 00:00:00 2001 From: damien Date: Mon, 19 Jul 2021 12:06:25 +0200 Subject: [PATCH 5/5] fix demos --- .../data-grid/sorting/BasicSortingGrid.tsx | 4 ++-- .../storybook/src/stories/grid-sorting.stories.tsx | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.tsx b/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.tsx index 42a6bee0a90a9..b337d3abbf86f 100644 --- a/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.tsx +++ b/docs/src/pages/components/data-grid/sorting/BasicSortingGrid.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { DataGrid, GridSortDirection, GridSortModel } from '@material-ui/data-grid'; +import { DataGrid, GridSortModel } from '@material-ui/data-grid'; import { useDemoData } from '@material-ui/x-grid-data-generator'; export default function BasicSortingGrid() { @@ -12,7 +12,7 @@ export default function BasicSortingGrid() { const [sortModel, setSortModel] = React.useState([ { field: 'commodity', - sort: 'asc' as GridSortDirection, + sort: 'asc', }, ]); diff --git a/packages/storybook/src/stories/grid-sorting.stories.tsx b/packages/storybook/src/stories/grid-sorting.stories.tsx index e2c50cca83bc0..7c3ff952d964c 100644 --- a/packages/storybook/src/stories/grid-sorting.stories.tsx +++ b/packages/storybook/src/stories/grid-sorting.stories.tsx @@ -438,7 +438,7 @@ function sortServerRows( return; } const sortedCol = sortModel[0]; - const comparator = columns[0].sortComparator!; + const comparator = columns.find((col) => col.field === sortedCol.field)!.sortComparator!; const clonedRows = [...rows]; let sortedRows = clonedRows.sort((a, b) => comparator(a[sortedCol.field], b[sortedCol.field], a, b), @@ -454,7 +454,9 @@ function sortServerRows( } export const ServerSideSorting = () => { + const apiRef = useGridApiRef(); const [rows, setRows] = React.useState(getRows()); + const [sortModel, setSortModel] = React.useState([{ field: 'age', sort: 'desc' }]); const [columns] = React.useState(getColumns()); const [loading, setLoading] = React.useState(false); @@ -463,19 +465,18 @@ export const ServerSideSorting = () => { setLoading(true); action('onSortModelChange')(model); - const newRows = await sortServerRows(rows, model, columns); + setSortModel(model); + const newRows = await sortServerRows(rows, model, apiRef.current.getVisibleColumns()); setRows(newRows); setLoading(false); }, - [columns, rows], + [apiRef, rows], ); - // We use `useMemo` here, to keep the same ref and not trigger another sort on the next rendering - const sortModel: GridSortModel = React.useMemo(() => [{ field: 'age', sort: 'desc' }], []); - return (