diff --git a/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.js b/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.js index 578bb95ba8afc..daa4469f24a30 100644 --- a/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.js +++ b/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.js @@ -1,6 +1,12 @@ import * as React from 'react'; import { DataGrid } from '@material-ui/data-grid'; +function getFullName(params) { + return `${params.getValue('firstName') || ''} ${ + params.getValue('lastName') || '' + }`; +} + const columns = [ { field: 'id', hide: true }, { field: 'firstName', headerName: 'First name', width: 130 }, @@ -9,10 +15,9 @@ const columns = [ field: 'fullName', headerName: 'Full name', width: 160, - valueGetter: (params) => - `${params.getValue('firstName') || ''} ${ - params.getValue('lastName') || '' - }`, + valueGetter: getFullName, + sortComparator: (v1, v2, cellParams1, cellParams2) => + getFullName(cellParams1).localeCompare(getFullName(cellParams2)), }, ]; diff --git a/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.tsx b/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.tsx index 01683a1fb7ce0..c1c270e498f18 100644 --- a/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.tsx +++ b/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.tsx @@ -1,6 +1,12 @@ import * as React from 'react'; import { DataGrid, ColDef, ValueGetterParams } from '@material-ui/data-grid'; +function getFullName(params: ValueGetterParams) { + return `${params.getValue('firstName') || ''} ${ + params.getValue('lastName') || '' + }`; +} + const columns: ColDef[] = [ { field: 'id', hide: true }, { field: 'firstName', headerName: 'First name', width: 130 }, @@ -9,10 +15,9 @@ const columns: ColDef[] = [ field: 'fullName', headerName: 'Full name', width: 160, - valueGetter: (params: ValueGetterParams) => - `${params.getValue('firstName') || ''} ${ - params.getValue('lastName') || '' - }`, + valueGetter: getFullName, + sortComparator: (v1, v2, cellParams1, cellParams2) => + getFullName(cellParams1).localeCompare(getFullName(cellParams2)), }, ]; diff --git a/docs/src/pages/components/data-grid/rendering/rendering.md b/docs/src/pages/components/data-grid/rendering/rendering.md index f810fc7398775..fb46472a5504e 100644 --- a/docs/src/pages/components/data-grid/rendering/rendering.md +++ b/docs/src/pages/components/data-grid/rendering/rendering.md @@ -13,9 +13,19 @@ This section is an extension of the main [column definitions documentation](/com ### Value getter -Sometimes a column might not have a corresponding value and you just want to render a combination of different fields. To do that, you can set the `valueGetter` attribute of `ColDef` as in the example below: +Sometimes a column might not have a corresponding value and you just want to render a combination of different fields. + +To do that, you can set the `valueGetter` attribute of `ColDef` as in the example below: + +**Note**: You need to set a `sortComparator` for the column sorting to work when setting the `valueGetter` attribute. ```tsx +function getFullName(params: ValueGetterParams) { + return `${params.getValue('firstName') || ''} ${ + params.getValue('lastName') || '' + }`; +} + const columns: ColDef[] = [ { field: 'id', hide: true }, { field: 'firstName', headerName: 'First name', width: 130 }, @@ -24,10 +34,9 @@ const columns: ColDef[] = [ field: 'fullName', headerName: 'Full name', width: 160, - valueGetter: (params: ValueGetterParams) => - `${params.getValue('firstName') || ''} ${ - params.getValue('lastName') || '' - }`, + valueGetter: getFullName, + sortComparator: (v1, v2, cellParams1, cellParams2) => + getFullName(cellParams1).localeCompare(getFullName(cellParams2)), }, ]; ``` diff --git a/packages/grid/_modules_/grid/hooks/features/useSorting.ts b/packages/grid/_modules_/grid/hooks/features/useSorting.ts index 49da05f1b82e3..5e1f14e5ace91 100644 --- a/packages/grid/_modules_/grid/hooks/features/useSorting.ts +++ b/packages/grid/_modules_/grid/hooks/features/useSorting.ts @@ -13,6 +13,7 @@ import { RowModel, RowsProp, SortApi, + CellParams, } from '../../models'; import { COLUMN_HEADER_CLICK, @@ -21,7 +22,7 @@ import { SORT_MODEL_CHANGE, } from '../../constants/eventsConstants'; import { useLogger } from '../utils'; -import { isDesc, nextSortDirection } from '../../utils'; +import { buildCellParams, isDesc, nextSortDirection } from '../../utils'; import { SortItem, SortModel } from '../../models/sortModel'; import { useApiEventHandler } from '../root/useApiEventHandler'; import { useApiMethod } from '../root/useApiMethod'; @@ -74,22 +75,42 @@ export const useSorting = ( [options.sortingOrder], ); - const comparatorListAggregate = React.useCallback((row1: RowModel, row2: RowModel) => { - const result = comparatorList.current.reduce((res, colComparator) => { - const { field, comparator } = colComparator; - res = res || comparator(row1.data[field], row2.data[field], row1, row2); - return res; - }, 0); - return result; - }, []); + const comparatorListAggregate = React.useCallback( + (row1: RowModel, row2: RowModel) => { + const result = comparatorList.current.reduce((res, colComparator) => { + const { field, comparator } = colComparator; + res = + res || + comparator( + row1.data[field], + row2.data[field], + buildCellParams({ + api: apiRef.current, + colDef: apiRef.current.getColumnFromField(field), + rowModel: row1, + value: row1.data[field], + }), + buildCellParams({ + api: apiRef.current, + colDef: apiRef.current.getColumnFromField(field), + rowModel: row2, + value: row2.data[field], + }), + ); + return res; + }, 0); + return result; + }, + [apiRef], + ); const buildComparatorList = React.useCallback( (sortModel: SortModel): FieldComparatorList => { const comparators = sortModel.map((item) => { const column = apiRef.current.getColumnFromField(item.field); const comparator = isDesc(item.sort) - ? (v1: CellValue, v2: CellValue, row1: RowModel, row2: RowModel) => - -1 * column.sortComparator!(v1, v2, row1, row2) + ? (v1: CellValue, v2: CellValue, cellParams1: CellParams, cellParams2: CellParams) => + -1 * column.sortComparator!(v1, v2, cellParams1, cellParams2) : column.sortComparator!; return { field: column.field, comparator }; }); diff --git a/packages/grid/_modules_/grid/models/params/cellParams.ts b/packages/grid/_modules_/grid/models/params/cellParams.ts index 2ba6630f7949c..7edad5b295c43 100644 --- a/packages/grid/_modules_/grid/models/params/cellParams.ts +++ b/packages/grid/_modules_/grid/models/params/cellParams.ts @@ -36,7 +36,7 @@ export interface CellParams { /** * The row index of the row that the current cell belongs to. */ - rowIndex: number; + rowIndex?: number; /** * ApiRef that let you manipulate the grid. */ diff --git a/packages/grid/_modules_/grid/models/sortModel.ts b/packages/grid/_modules_/grid/models/sortModel.ts index 6f52124fde3d0..6adb021ebcdf0 100644 --- a/packages/grid/_modules_/grid/models/sortModel.ts +++ b/packages/grid/_modules_/grid/models/sortModel.ts @@ -1,4 +1,5 @@ -import { CellValue, RowModel } from './rows'; +import { CellValue } from './rows'; +import { CellParams } from './params/cellParams'; export type SortDirection = 'asc' | 'desc' | null | undefined; @@ -7,7 +8,12 @@ export type FieldComparatorList = { field: string; comparator: ComparatorFn }[]; /** * The type of the sort comparison function. */ -export type ComparatorFn = (v1: CellValue, v2: CellValue, row1: RowModel, row2: RowModel) => number; +export type ComparatorFn = ( + v1: CellValue, + v2: CellValue, + cellParams1: CellParams, + cellParams2: CellParams, +) => number; /** * Object that represents the column sorted data, part of the [[SortModel]]. diff --git a/packages/grid/_modules_/grid/utils/paramsUtils.ts b/packages/grid/_modules_/grid/utils/paramsUtils.ts index 5d3b2d582c638..626c329b36ce2 100644 --- a/packages/grid/_modules_/grid/utils/paramsUtils.ts +++ b/packages/grid/_modules_/grid/utils/paramsUtils.ts @@ -14,7 +14,7 @@ export function buildCellParams({ }: { rowModel: RowModel; colDef: ColDef; - rowIndex: number; + rowIndex?: number; value: CellValue; api: GridApi; element?: HTMLElement; diff --git a/packages/storybook/src/stories/grid-sorting.stories.tsx b/packages/storybook/src/stories/grid-sorting.stories.tsx index 371da5e933cff..13208c4f6a879 100644 --- a/packages/storybook/src/stories/grid-sorting.stories.tsx +++ b/packages/storybook/src/stories/grid-sorting.stories.tsx @@ -221,7 +221,8 @@ export const CustomComparator = () => { field: 'username', valueGetter: (params) => `${params.getValue('name') || 'unknown'}_${params.getValue('age') || 'x'}`, - sortComparator: (v1, v2, row1, row2) => row1.data.age - row2.data.age, + sortComparator: (v1, v2, cellParams1, cellParams2) => + cellParams1.data.age - cellParams2.data.age, sortDirection: 'asc', width: 150, };