diff --git a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.spec.tsx b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.spec.tsx
index b3f15cedba6..632203cb80e 100644
--- a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.spec.tsx
+++ b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.spec.tsx
@@ -10,7 +10,7 @@ import {
import { ThemeProvider, createTheme } from '@mui/material';
import { Datagrid } from './Datagrid';
-import { AccessControl, SelectAllButton } from './Datagrid.stories';
+import { AccessControl, FullApp, SelectAllButton } from './Datagrid.stories';
const TitleField = () => {
const record = useRecordContext();
@@ -126,6 +126,36 @@ describe('', () => {
expect(screen.queryByText('Select All')).toBeNull();
});
+ describe('row selection', () => {
+ it('should reveal bulk delete button by default on row selection', async () => {
+ render();
+ const checkboxes = await screen.findAllByRole('checkbox');
+ fireEvent.click(checkboxes[1]);
+ await screen.findByLabelText('Delete');
+ await screen.findByText('1 item selected');
+ fireEvent.click(checkboxes[2]);
+ await screen.findByText('2 items selected');
+ });
+ it('should reveal select all button when selecting the entire page', async () => {
+ render();
+ const checkboxes = await screen.findAllByRole('checkbox');
+ fireEvent.click(checkboxes[0]);
+ const selectAllButton = await screen.findByText('Select all');
+ selectAllButton.click();
+ await screen.findByText('7 items selected');
+ });
+ it('should only unselect the current page records', async () => {
+ render();
+ const checkboxes = await screen.findAllByRole('checkbox');
+ fireEvent.click(checkboxes[0]);
+ const selectAllButton = await screen.findByText('Select all');
+ selectAllButton.click();
+ await screen.findByText('7 items selected');
+ fireEvent.click(checkboxes[0]);
+ await screen.findByText('2 items selected');
+ });
+ });
+
describe('selecting items with the shift key', () => {
it('should call onSelect with the correct ids when the last selection is after the first', () => {
const Test = ({ selectedIds = [] }) => (
diff --git a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.stories.tsx b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.stories.tsx
index 07e791d16e1..7f77ef9ee09 100644
--- a/packages/ra-ui-materialui/src/list/datagrid/Datagrid.stories.tsx
+++ b/packages/ra-ui-materialui/src/list/datagrid/Datagrid.stories.tsx
@@ -10,6 +10,7 @@ import {
TestMemoryRouter,
SortPayload,
AuthProvider,
+ memoryStore,
} from 'ra-core';
import fakeRestDataProvider from 'ra-data-fakerest';
import defaultMessages from 'ra-language-english';
@@ -558,18 +559,21 @@ export const RowClickFalse = () => (
export const FullApp = ({
rowClick,
+ perPage = undefined,
}: {
rowClick?: DatagridRowProps['rowClick'];
+ perPage?: number;
}) => (
defaultMessages, 'en')}
+ store={memoryStore()}
>
(
-
+
}
rowClick={rowClick}
diff --git a/packages/ra-ui-materialui/src/list/datagrid/DatagridHeader.tsx b/packages/ra-ui-materialui/src/list/datagrid/DatagridHeader.tsx
index 55c2186928a..6e4e44288af 100644
--- a/packages/ra-ui-materialui/src/list/datagrid/DatagridHeader.tsx
+++ b/packages/ra-ui-materialui/src/list/datagrid/DatagridHeader.tsx
@@ -58,17 +58,18 @@ export const DatagridHeader = (props: DatagridHeaderProps) => {
event.target.checked
? selectedIds.concat(
data
- .filter(
- record => !selectedIds.includes(record.id)
- )
.filter(record =>
+ !selectedIds.includes(record.id) &&
isRowSelectable
? isRowSelectable(record)
: true
)
.map(record => record.id)
)
- : []
+ : // We should only unselect the ids present in the current page
+ selectedIds.filter(
+ id => !data.some(record => record.id === id)
+ )
);
},
[data, onSelect, isRowSelectable, selectedIds]
diff --git a/packages/ra-ui-materialui/src/list/datatable/DataTable.spec.tsx b/packages/ra-ui-materialui/src/list/datatable/DataTable.spec.tsx
index 2eadc6c78b5..1b7d20aacb5 100644
--- a/packages/ra-ui-materialui/src/list/datatable/DataTable.spec.tsx
+++ b/packages/ra-ui-materialui/src/list/datatable/DataTable.spec.tsx
@@ -235,6 +235,16 @@ describe('DataTable', () => {
selectAllButton.click();
await screen.findByText('7 items selected');
});
+ it('should only unselect the current page records', async () => {
+ render();
+ const checkboxes = await screen.findAllByRole('checkbox');
+ fireEvent.click(checkboxes[0]);
+ const selectAllButton = await screen.findByText('Select all');
+ selectAllButton.click();
+ await screen.findByText('7 items selected');
+ fireEvent.click(checkboxes[0]);
+ await screen.findByText('2 items selected');
+ });
});
describe('isRowSelectable', () => {
it('should allow to disable row selection', async () => {
diff --git a/packages/ra-ui-materialui/src/list/datatable/SelectPageCheckbox.tsx b/packages/ra-ui-materialui/src/list/datatable/SelectPageCheckbox.tsx
index c4c726bf859..48b67f2fe78 100644
--- a/packages/ra-ui-materialui/src/list/datatable/SelectPageCheckbox.tsx
+++ b/packages/ra-ui-materialui/src/list/datatable/SelectPageCheckbox.tsx
@@ -22,17 +22,18 @@ export const SelectPageCheckbox = () => {
event.target.checked
? selectedIds.concat(
data
- .filter(
- record => !selectedIds.includes(record.id)
- )
.filter(record =>
+ !selectedIds.includes(record.id) &&
isRowSelectable
? isRowSelectable(record)
: true
)
.map(record => record.id)
)
- : []
+ : // We should only unselect the ids present in the current page
+ selectedIds.filter(
+ id => !data.some(record => record.id === id)
+ )
);
},
[data, onSelect, isRowSelectable, selectedIds]