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(() => {