Skip to content

Commit

Permalink
[DataGrid] Fix checkboxSelectionVisibleOnly reset the selection on …
Browse files Browse the repository at this point in the history
…filtering (#14677)

Signed-off-by: Bilal Shafi <bilalshafidev@gmail.com>
Co-authored-by: Armin Mehinovic <4390250+arminmeh@users.noreply.github.com>
  • Loading branch information
MBilalShafi and arminmeh authored Sep 28, 2024
1 parent 1cfe453 commit 50f9889
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,43 @@ describe('<DataGridPro /> - 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(
<TestDataGridSelection
rowLength={50}
checkboxSelection
checkboxSelectionVisibleOnly
initialState={{
pagination: { paginationModel: { pageSize: 2 } },
filter: {
filterModel: {
items: [
{
field: 'currencyPair',
value: 'usd',
operator: 'contains',
},
],
},
},
}}
pagination
pageSizeOptions={[2]}
/>,
);

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', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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';
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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],
);
Expand Down Expand Up @@ -539,6 +537,11 @@ export const useGridRowSelection = (
'sortedRowsSet',
runIfRowSelectionIsEnabled(removeOutdatedSelection),
);
useGridApiEventHandler(
apiRef,
'filteredRowsSet',
runIfRowSelectionIsEnabled(removeOutdatedSelection),
);
useGridApiEventHandler(apiRef, 'rowClick', runIfRowSelectionIsEnabled(handleRowClick));
useGridApiEventHandler(
apiRef,
Expand Down
36 changes: 34 additions & 2 deletions packages/x-data-grid/src/tests/rowSelection.DataGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,38 @@ describe('<DataGrid /> - 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(
<TestDataGridSelection
checkboxSelection
initialState={{
preferencePanel: {
open: true,
openedPanelValue: GridPreferencePanelsValue.filters,
},
}}
/>,
);
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(
<TestDataGridSelection
Expand All @@ -390,10 +422,10 @@ describe('<DataGrid /> - 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(() => {
Expand Down

0 comments on commit 50f9889

Please sign in to comment.