diff --git a/packages/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts b/packages/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts index 353b51936bd4..38d201c989d7 100644 --- a/packages/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts +++ b/packages/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts @@ -10,6 +10,7 @@ import { GridColDef, GridKeyValue, GridDataSource, + gridColumnFieldsSelector, } from '@mui/x-data-grid-pro'; import { passFilterLogic, @@ -50,11 +51,27 @@ export const getRowGroupingFieldFromGroupingCriteria = (groupingCriteria: string return `__row_group_by_columns_group_${groupingCriteria}__`; }; +export const getColDefOverrides = ( + groupingColDefProp: DataGridPremiumProcessedProps['groupingColDef'], + fields: string[], + strategy?: RowGroupingStrategy, +) => { + if (typeof groupingColDefProp === 'function') { + return groupingColDefProp({ + groupingName: strategy ?? RowGroupingStrategy.Default, + fields, + }); + } + return groupingColDefProp; +}; + interface FilterRowTreeFromTreeDataParams { rowTree: GridRowTreeConfig; isRowMatchingFilters: GridAggregatedFilterItemApplier | null; filterModel: GridFilterModel; apiRef: React.MutableRefObject; + rowGroupingColumnMode: 'single' | 'multiple'; + groupingColDef: DataGridPremiumProcessedProps['groupingColDef']; } /** @@ -79,15 +96,71 @@ const shouldApplyFilterItemOnGroup = (columnField: string, node: GridGroupNode) export const filterRowTreeFromGroupingColumns = ( params: FilterRowTreeFromTreeDataParams, ): Omit => { - const { apiRef, rowTree, isRowMatchingFilters, filterModel } = params; + const { + apiRef, + rowTree, + isRowMatchingFilters, + filterModel, + rowGroupingColumnMode, + groupingColDef, + } = params; const filteredRowsLookup: Record = {}; const filteredChildrenCountLookup: Record = {}; const filteredDescendantCountLookup: Record = {}; const filterCache = {}; + const getGroupingCriteria = () => { + const rowGroupingModel = gridRowGroupingSanitizedModelSelector(apiRef); + const colDefOverride = getColDefOverrides(groupingColDef, rowGroupingModel); + const orderedFields = gridColumnFieldsSelector(apiRef); + const { leafField, mainGroupingCriteria } = colDefOverride ?? {}; + const isLeafField = leafField ? orderedFields.includes(leafField) : null; + if (mainGroupingCriteria && rowGroupingModel.includes(mainGroupingCriteria)) { + return mainGroupingCriteria; + } + if (isLeafField) { + return null; + } + return rowGroupingModel[0]; + }; + + const shouldFilterGroup = (node: GridTreeNode): boolean => { + if (node.type === 'group' && node.isAutoGenerated) { + const groupingCriteria = getGroupingCriteria(); + if (!groupingCriteria) { + return false; + } + const groupingField = getRowGroupingFieldFromGroupingCriteria(groupingCriteria); + const groupFilterItems: string[] = [groupingField]; + const leafFilterItems: string[] = []; + filterModel.items.forEach((item) => { + if (isGroupingColumn(item.field)) { + groupFilterItems.push(item.field); + } else { + leafFilterItems.push(item.field); + } + }); + + if (leafFilterItems.length > 0 || filterModel.quickFilterValues?.length! > 0) { + return false; + } + + const nodeGroupingField = getRowGroupingFieldFromGroupingCriteria(node.groupingField); + + if (rowGroupingColumnMode === 'multiple') { + return nodeGroupingField === groupFilterItems[groupFilterItems.length - 1]; + } + return nodeGroupingField === groupFilterItems[0]; + } + + return false; + }; + const filterTreeNode = ( node: GridTreeNode, areAncestorsExpanded: boolean, + isParentPassingFilter: boolean, + shouldFilterParent: boolean, ancestorsResults: GridAggregatedFilterItemApplierResult[], ): number => { const filterResults: GridAggregatedFilterItemApplierResult = { @@ -96,7 +169,7 @@ export const filterRowTreeFromGroupingColumns = ( }; let isPassingFiltering = false; - + let allowGroupToFilter = shouldFilterGroup(node); if (isRowMatchingFilters && node.type !== 'footer') { const shouldApplyItem = node.type === 'group' && node.isAutoGenerated @@ -105,18 +178,33 @@ export const filterRowTreeFromGroupingColumns = ( const row = apiRef.current.getRow(node.id); isRowMatchingFilters(row, shouldApplyItem, filterResults); + const allResults = [...ancestorsResults, filterResults]; + isPassingFiltering = passFilterLogic( + allResults.map((result) => result.passingFilterItems), + allResults.map((result) => result.passingQuickFilterValues), + filterModel, + params.apiRef, + filterCache, + ); } else { isPassingFiltering = true; } let filteredChildrenCount = 0; let filteredDescendantCount = 0; + + if (shouldFilterParent && node.type !== 'footer') { + isPassingFiltering = isParentPassingFilter; + allowGroupToFilter = shouldFilterParent; + } if (node.type === 'group') { node.children.forEach((childId) => { const childNode = rowTree[childId]; const childSubTreeSize = filterTreeNode( childNode, areAncestorsExpanded && !!node.childrenExpanded, + isPassingFiltering, + allowGroupToFilter, [...ancestorsResults, filterResults], ); filteredDescendantCount += childSubTreeSize; @@ -126,20 +214,8 @@ export const filterRowTreeFromGroupingColumns = ( }); } - if (isPassingFiltering === false) { - if (node.type === 'group') { - // If node has children - it's passing if at least one child passes filters - isPassingFiltering = filteredDescendantCount > 0; - } else { - const allResults = [...ancestorsResults, filterResults]; - isPassingFiltering = passFilterLogic( - allResults.map((result) => result.passingFilterItems), - allResults.map((result) => result.passingQuickFilterValues), - filterModel, - params.apiRef, - filterCache, - ); - } + if (node.type === 'group' && !shouldFilterParent) { + isPassingFiltering = filteredDescendantCount > 0; } filteredRowsLookup[node.id] = isPassingFiltering; @@ -162,7 +238,7 @@ export const filterRowTreeFromGroupingColumns = ( for (let i = 0; i < nodes.length; i += 1) { const node = nodes[i]; if (node.depth === 0) { - filterTreeNode(node, true, []); + filterTreeNode(node, true, true, false, []); } } @@ -173,21 +249,6 @@ export const filterRowTreeFromGroupingColumns = ( }; }; -export const getColDefOverrides = ( - groupingColDefProp: DataGridPremiumProcessedProps['groupingColDef'], - fields: string[], - strategy?: RowGroupingStrategy, -) => { - if (typeof groupingColDefProp === 'function') { - return groupingColDefProp({ - groupingName: strategy ?? RowGroupingStrategy.Default, - fields, - }); - } - - return groupingColDefProp; -}; - export const mergeStateWithRowGroupingModel = (rowGroupingModel: GridRowGroupingModel) => (state: GridStatePremium): GridStatePremium => ({ diff --git a/packages/x-data-grid-premium/src/hooks/features/rowGrouping/useGridRowGroupingPreProcessors.ts b/packages/x-data-grid-premium/src/hooks/features/rowGrouping/useGridRowGroupingPreProcessors.ts index 435ac1ca1a7e..be0b6c0e33da 100644 --- a/packages/x-data-grid-premium/src/hooks/features/rowGrouping/useGridRowGroupingPreProcessors.ts +++ b/packages/x-data-grid-premium/src/hooks/features/rowGrouping/useGridRowGroupingPreProcessors.ts @@ -225,9 +225,11 @@ export const useGridRowGroupingPreProcessors = ( isRowMatchingFilters: params.isRowMatchingFilters, filterModel: params.filterModel, apiRef, + rowGroupingColumnMode: props.rowGroupingColumnMode, + groupingColDef: props.groupingColDef, }); }, - [apiRef], + [apiRef, props.groupingColDef, props.rowGroupingColumnMode], ); const sortRows = React.useCallback>( diff --git a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx index 6a0979cff342..0ff9f89787fd 100644 --- a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx @@ -2406,7 +2406,7 @@ describe(' - Row grouping', () => { />, ); - // Corresponds to rows id 0, 1, 2 because of Cat A, ann id 4 because of Cat 1 + // Corresponds to rows id 0 because of Cat A, ann id 4 because of Cat 1 expect(getColumnValues(1)).to.deep.equal(['', '0', '1', '2', '', '4']); });