From 94f09ed27fb427e1d567563ef0e8d02dbf3f05cb Mon Sep 17 00:00:00 2001 From: Andrew Cherniavskii Date: Mon, 6 Nov 2023 14:33:07 +0100 Subject: [PATCH] [DataGrid] Fix cell value type in quick filtering v7 (#10884) --- docs/pages/x/api/data-grid/grid-api.md | 1 + .../pages/x/api/data-grid/grid-filter-api.json | 5 +++++ .../clipboard/useGridClipboardImport.ts | 3 ++- .../src/colDef/gridStringOperators.ts | 7 ++++++- .../hooks/features/filter/gridFilterUtils.ts | 18 +++++++++++------- .../hooks/features/filter/useGridFilter.tsx | 2 ++ .../grid/x-data-grid/src/internals/index.ts | 1 + .../src/models/api/gridFilterApi.ts | 5 +++++ .../x-data-grid/src/utils/getPublicApiRef.ts | 9 +++++++++ 9 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 packages/grid/x-data-grid/src/utils/getPublicApiRef.ts diff --git a/docs/pages/x/api/data-grid/grid-api.md b/docs/pages/x/api/data-grid/grid-api.md index 82c74b0cea43..255aa9b096bf 100644 --- a/docs/pages/x/api/data-grid/grid-api.md +++ b/docs/pages/x/api/data-grid/grid-api.md @@ -74,6 +74,7 @@ import { GridApi } from '@mui/x-data-grid'; | hideFilterPanel | () => void | Hides the filter panel. | | hideHeaderFilterMenu | () => void | Hides the header filter menu. | | hidePreferences | () => void | Hides the preferences panel. | +| ignoreDiacritics | DataGridProcessedProps['ignoreDiacritics'] | Returns the value of the `ignoreDiacritics` prop. | | isCellEditable | (params: GridCellParams) => boolean | Controls if a cell is editable. | | isColumnPinned [](/x/introduction/licensing/#pro-plan) | (field: string) => GridPinnedPosition \| false | Returns which side a column is pinned to. | | isRowSelectable | (id: GridRowId) => boolean | Determines if a row can be selected or not. | diff --git a/docs/pages/x/api/data-grid/grid-filter-api.json b/docs/pages/x/api/data-grid/grid-filter-api.json index c80e144545f8..626ae4fcb29e 100644 --- a/docs/pages/x/api/data-grid/grid-filter-api.json +++ b/docs/pages/x/api/data-grid/grid-filter-api.json @@ -8,6 +8,11 @@ "type": "(item: GridFilterItem) => void" }, { "name": "hideFilterPanel", "description": "Hides the filter panel.", "type": "() => void" }, + { + "name": "ignoreDiacritics", + "description": "Returns the value of the ignoreDiacritics prop.", + "type": "DataGridProcessedProps['ignoreDiacritics']" + }, { "name": "setFilterLogicOperator", "description": "Changes the GridLogicOperator used to connect the filters.", diff --git a/packages/grid/x-data-grid-premium/src/hooks/features/clipboard/useGridClipboardImport.ts b/packages/grid/x-data-grid-premium/src/hooks/features/clipboard/useGridClipboardImport.ts index c4dc4ac80dfd..2c36a29fc294 100644 --- a/packages/grid/x-data-grid-premium/src/hooks/features/clipboard/useGridClipboardImport.ts +++ b/packages/grid/x-data-grid-premium/src/hooks/features/clipboard/useGridClipboardImport.ts @@ -19,6 +19,7 @@ import { getActiveElement, GridPipeProcessor, useGridRegisterPipeProcessor, + getPublicApiRef, } from '@mui/x-data-grid/internals'; import { GRID_DETAIL_PANEL_TOGGLE_FIELD, GRID_REORDER_COL_DEF } from '@mui/x-data-grid-pro'; import { unstable_debounce as debounce } from '@mui/utils'; @@ -379,7 +380,7 @@ export const useGridClipboardImport = ( defaultPasteResolver({ pastedData, - apiRef: { current: apiRef.current.getPublicApi() }, + apiRef: getPublicApiRef(apiRef), updateCell: (...args) => { cellUpdater.updateCell(...args); }, diff --git a/packages/grid/x-data-grid/src/colDef/gridStringOperators.ts b/packages/grid/x-data-grid/src/colDef/gridStringOperators.ts index aa875f803a13..dca999638aa8 100644 --- a/packages/grid/x-data-grid/src/colDef/gridStringOperators.ts +++ b/packages/grid/x-data-grid/src/colDef/gridStringOperators.ts @@ -5,6 +5,7 @@ import { GridFilterItem } from '../models/gridFilterItem'; import { GridFilterOperator } from '../models/gridFilterOperator'; import { GridFilterInputMultipleValue } from '../components/panel/filterPanel/GridFilterInputMultipleValue'; import { convertLegacyOperators, tagInternalFilter } from './utils'; +import { removeDiacritics } from '../hooks/features/filter/gridFilterUtils'; export const getGridStringQuickFilterFn = tagInternalFilter( (value: any): GridApplyQuickFilterV7 | null => { @@ -12,7 +13,11 @@ export const getGridStringQuickFilterFn = tagInternalFilter( return null; } const filterRegex = new RegExp(escapeRegExp(value), 'i'); - return (columnValue): boolean => { + return (_, row, column, apiRef): boolean => { + let columnValue = apiRef.current.getRowFormattedValue(row, column); + if (apiRef.current.ignoreDiacritics) { + columnValue = removeDiacritics(columnValue); + } return columnValue != null ? filterRegex.test(columnValue.toString()) : false; }; }, diff --git a/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterUtils.ts b/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterUtils.ts index a4418aa3626d..e719d42760de 100644 --- a/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterUtils.ts +++ b/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterUtils.ts @@ -18,6 +18,7 @@ import { GridQuickFilterValueResult, } from './gridFilterState'; import { buildWarning } from '../../../utils/warning'; +import { getPublicApiRef } from '../../../utils/getPublicApiRef'; import { gridColumnFieldsSelector, gridColumnLookupSelector, @@ -152,7 +153,7 @@ export const mergeStateWithFilterModel = filterModel: sanitizeFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef), }); -const removeDiacritics = (value: unknown) => { +export const removeDiacritics = (value: unknown) => { if (typeof value === 'string') { return value.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); } @@ -207,6 +208,8 @@ const getFilterCallbackFromItem = ( const hasUserFunctionLegacy = !isInternalFilter(filterOperator.getApplyFilterFn); const hasUserFunctionV7 = !isInternalFilter(filterOperator.getApplyFilterFnV7); + const publicApiRef = getPublicApiRef(apiRef); + if (filterOperator.getApplyFilterFnV7 && !(hasUserFunctionLegacy && !hasUserFunctionV7)) { const applyFilterOnRow = filterOperator.getApplyFilterFnV7(newFilterItem, column)!; if (typeof applyFilterOnRow !== 'function') { @@ -220,7 +223,7 @@ const getFilterCallbackFromItem = ( if (ignoreDiacritics) { value = removeDiacritics(value); } - return applyFilterOnRow(value, row, column, apiRef); + return applyFilterOnRow(value, row, column, publicApiRef); }, }; } @@ -235,7 +238,7 @@ const getFilterCallbackFromItem = ( item: newFilterItem, fn: (rowId: GridRowId) => { const params = apiRef.current.getCellParams(rowId, newFilterItem.field!); - GLOBAL_API_REF.current = apiRef; + GLOBAL_API_REF.current = publicApiRef; if (ignoreDiacritics) { params.value = removeDiacritics(params.value); } @@ -355,6 +358,7 @@ const buildAggregatedQuickFilterApplier = ( }[]; const { ignoreDiacritics } = apiRef.current.rootProps; + const publicApiRef = getPublicApiRef(apiRef); columnFields.forEach((field) => { const column = apiRef.current.getColumn(field); @@ -371,7 +375,7 @@ const buildAggregatedQuickFilterApplier = ( const value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue; return { v7: true, - fn: getApplyQuickFilterFnV7(value, column, apiRef), + fn: getApplyQuickFilterFnV7(value, column, publicApiRef), }; }), }); @@ -382,7 +386,7 @@ const buildAggregatedQuickFilterApplier = ( const value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue; return { v7: false, - fn: getApplyQuickFilterFn(value, column, apiRef), + fn: getApplyQuickFilterFn(value, column, publicApiRef), }; }), }); @@ -406,7 +410,7 @@ const buildAggregatedQuickFilterApplier = ( } const applier = appliers[v]; - let value = apiRef.current.getRowFormattedValue(row, column); + let value = apiRef.current.getRowValue(row, column); if (applier.fn === null) { continue; @@ -416,7 +420,7 @@ const buildAggregatedQuickFilterApplier = ( if (ignoreDiacritics) { value = removeDiacritics(value); } - const isMatching = applier.fn(value, row, column, apiRef); + const isMatching = applier.fn(value, row, column, publicApiRef); if (isMatching) { result[filterValue] = true; continue outer; diff --git a/packages/grid/x-data-grid/src/hooks/features/filter/useGridFilter.tsx b/packages/grid/x-data-grid/src/hooks/features/filter/useGridFilter.tsx index 6e70483397e0..166e52a5ced0 100644 --- a/packages/grid/x-data-grid/src/hooks/features/filter/useGridFilter.tsx +++ b/packages/grid/x-data-grid/src/hooks/features/filter/useGridFilter.tsx @@ -90,6 +90,7 @@ export const useGridFilter = ( | 'slotProps' | 'disableColumnFilter' | 'disableEval' + | 'ignoreDiacritics' >, ): void => { const logger = useGridLogger(apiRef, 'useGridFilter'); @@ -329,6 +330,7 @@ export const useGridFilter = ( showFilterPanel, hideFilterPanel, setQuickFilterValues, + ignoreDiacritics: props.ignoreDiacritics, }; useGridApiMethod(apiRef, filterApi, 'public'); diff --git a/packages/grid/x-data-grid/src/internals/index.ts b/packages/grid/x-data-grid/src/internals/index.ts index 282be9d71386..8b5cd1a8c102 100644 --- a/packages/grid/x-data-grid/src/internals/index.ts +++ b/packages/grid/x-data-grid/src/internals/index.ts @@ -141,6 +141,7 @@ export { isNavigationKey } from '../utils/keyboardUtils'; export { clamp, isDeepEqual, isNumber, isFunction, isObject } from '../utils/utils'; export { buildWarning } from '../utils/warning'; export { exportAs } from '../utils/exportAs'; +export * from '../utils/getPublicApiRef'; export type { GridPrivateOnlyApiCommon } from '../models/api/gridApiCommon'; export { useGridPrivateApiContext } from '../hooks/utils/useGridPrivateApiContext'; export * from '../hooks/utils/useOnMount'; diff --git a/packages/grid/x-data-grid/src/models/api/gridFilterApi.ts b/packages/grid/x-data-grid/src/models/api/gridFilterApi.ts index 546c0787bd43..16f3b6194f99 100644 --- a/packages/grid/x-data-grid/src/models/api/gridFilterApi.ts +++ b/packages/grid/x-data-grid/src/models/api/gridFilterApi.ts @@ -1,6 +1,7 @@ import { GridFilterModel } from '../gridFilterModel'; import { GridFilterItem, GridLogicOperator } from '../gridFilterItem'; import { GridControlledStateReasonLookup } from '../events'; +import { DataGridProcessedProps } from '../props/DataGridProps'; /** * The filter API interface that is available in the grid [[apiRef]]. @@ -56,4 +57,8 @@ export interface GridFilterApi { * @param {any[]} values The list of element to quick filter */ setQuickFilterValues: (values: any[]) => void; + /** + * Returns the value of the `ignoreDiacritics` prop. + */ + ignoreDiacritics: DataGridProcessedProps['ignoreDiacritics']; } diff --git a/packages/grid/x-data-grid/src/utils/getPublicApiRef.ts b/packages/grid/x-data-grid/src/utils/getPublicApiRef.ts new file mode 100644 index 000000000000..0f1a980ad93b --- /dev/null +++ b/packages/grid/x-data-grid/src/utils/getPublicApiRef.ts @@ -0,0 +1,9 @@ +import type { GridPrivateApiCommunity } from '../models/api/gridApiCommunity'; + +export function getPublicApiRef( + apiRef: React.MutableRefObject, +) { + return { current: apiRef.current.getPublicApi() } as React.MutableRefObject< + ReturnType + >; +}