diff --git a/packages/x-data-grid-pro/src/tests/rowSelection.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/rowSelection.DataGridPro.test.tsx index 8d0af590260d4..f878b572a3c51 100644 --- a/packages/x-data-grid-pro/src/tests/rowSelection.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/rowSelection.DataGridPro.test.tsx @@ -253,6 +253,43 @@ describe(' - Row selection', () => { fireEvent.click(selectAllCheckbox); expect(apiRef.current.getSelectedRows()).to.have.length(2); }); + + // https://github.com/mui/mui-x/issues/14074 + it('should select all the rows of the current page keeping the previously selected rows when a filter is applied', () => { + render( + , + ); + + fireEvent.click(getCell(0, 0).querySelector('input')!); + expect(apiRef.current.getSelectedRows()).to.have.keys([0]); + fireEvent.click(screen.getByRole('button', { name: /next page/i })); + const selectAllCheckbox: HTMLInputElement = screen.getByRole('checkbox', { + name: /select all rows/i, + }); + fireEvent.click(selectAllCheckbox); + expect(apiRef.current.getSelectedRows()).to.have.keys([0, 3, 4]); + expect(selectAllCheckbox.checked).to.equal(true); + }); }); describe('apiRef: getSelectedRows', () => { diff --git a/packages/x-data-grid/src/hooks/features/rowSelection/useGridRowSelection.ts b/packages/x-data-grid/src/hooks/features/rowSelection/useGridRowSelection.ts index e42e696554f9e..337b324e48b59 100644 --- a/packages/x-data-grid/src/hooks/features/rowSelection/useGridRowSelection.ts +++ b/packages/x-data-grid/src/hooks/features/rowSelection/useGridRowSelection.ts @@ -10,7 +10,6 @@ import { GridRowId } from '../../../models/gridRows'; import { GridSignature, useGridApiEventHandler } from '../../utils/useGridApiEventHandler'; import { useGridApiMethod } from '../../utils/useGridApiMethod'; import { useGridLogger } from '../../utils/useGridLogger'; -import { gridRowsLookupSelector } from '../rows/gridRowsSelector'; import { gridRowSelectionStateSelector, selectedGridRowsSelector, @@ -20,7 +19,7 @@ import { gridPaginatedVisibleSortedGridRowIdsSelector } from '../pagination'; import { gridFocusCellSelector } from '../focus/gridFocusStateSelector'; import { gridExpandedSortedRowIdsSelector, - gridFilterModelSelector, + gridFilteredRowsLookupSelector, } from '../filter/gridFilterSelector'; import { GRID_CHECKBOX_SELECTION_COL_DEF, GRID_ACTIONS_COLUMN_TYPE } from '../../../colDef'; import { GridCellModes } from '../../../models/gridEditRowModel'; @@ -331,14 +330,14 @@ export const useGridRowSelection = ( return; } const currentSelection = gridRowSelectionStateSelector(apiRef.current.state); - const rowsLookup = gridRowsLookupSelector(apiRef); + const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef); // We clone the existing object to avoid mutating the same object returned by the selector to others part of the project const selectionLookup = { ...selectedIdsLookupSelector(apiRef) }; let hasChanged = false; currentSelection.forEach((id: GridRowId) => { - if (!rowsLookup[id]) { + if (!filteredRowsLookup[id]) { delete selectionLookup[id]; hasChanged = true; } @@ -452,8 +451,7 @@ export const useGridRowSelection = ( ? gridPaginatedVisibleSortedGridRowIdsSelector(apiRef) : gridExpandedSortedRowIdsSelector(apiRef); - const filterModel = gridFilterModelSelector(apiRef); - apiRef.current.selectRows(rowsToBeSelected, params.value, filterModel?.items.length > 0); + apiRef.current.selectRows(rowsToBeSelected, params.value); }, [apiRef, props.checkboxSelectionVisibleOnly, props.pagination, props.paginationMode], ); @@ -539,6 +537,11 @@ export const useGridRowSelection = ( 'sortedRowsSet', runIfRowSelectionIsEnabled(removeOutdatedSelection), ); + useGridApiEventHandler( + apiRef, + 'filteredRowsSet', + runIfRowSelectionIsEnabled(removeOutdatedSelection), + ); useGridApiEventHandler(apiRef, 'rowClick', runIfRowSelectionIsEnabled(handleRowClick)); useGridApiEventHandler( apiRef, diff --git a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx index 45ddd727ca212..67f6e8350ca23 100644 --- a/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx @@ -367,6 +367,38 @@ describe(' - Row selection', () => { expect(input2.checked).to.equal(true); }); + it('should remove the selection from rows that are filtered out', async function test() { + if (isJSDOM) { + this.skip(); + } + render( + , + ); + const selectAllCheckbox = screen.getByRole('checkbox', { name: 'Select all rows' }); + fireEvent.click(selectAllCheckbox); + await act(() => { + expect(getSelectedRowIds()).to.deep.equal([0, 1, 2, 3]); + }); + expect(grid('selectedRowCount')?.textContent).to.equal('4 rows selected'); + + fireEvent.change(screen.getByRole('spinbutton', { name: 'Value' }), { + target: { value: 1 }, + }); + await waitFor(() => { + // Previous selection is cleaned with only the filtered rows + expect(getSelectedRowIds()).to.deep.equal([1]); + }); + expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); + }); + it('should only select filtered items when "select all" is toggled after applying a filter', async () => { render( - Row selection', () => { target: { value: 1 }, }); await waitFor(() => { - // Previous selection remains, but only one row is visible + // Previous selection is cleared and only the filtered row is selected expect(getSelectedRowIds()).to.deep.equal([1]); }); - expect(grid('selectedRowCount')?.textContent).to.equal('4 rows selected'); + expect(grid('selectedRowCount')?.textContent).to.equal('1 row selected'); fireEvent.click(selectAllCheckbox); // Unselect all await waitFor(() => {