Skip to content

Commit 4b23874

Browse files
committed
Fix : ensure table selections respect applied filters
Signed-off-by: Ayoub LABIDI <[email protected]>
1 parent c85cbba commit 4b23874

File tree

4 files changed

+32
-28
lines changed

4 files changed

+32
-28
lines changed

src/pages/groups/groups-table.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ import { useIntl } from 'react-intl';
1010
import { GroupAdd } from '@mui/icons-material';
1111
import { GridButton, GridButtonDelete, GridTable, GridTableRef } from '../../components/Grid';
1212
import { GroupInfos, UserAdminSrv, UserInfos } from '../../services';
13-
import { ColDef, GetRowIdParams, RowClickedEvent, SelectionChangedEvent, TextFilterParams } from 'ag-grid-community';
13+
import { ColDef, GetRowIdParams, RowClickedEvent, TextFilterParams } from 'ag-grid-community';
1414
import { useSnackMessage } from '@gridsuite/commons-ui';
1515
import DeleteConfirmationDialog from '../common/delete-confirmation-dialog';
1616
import { defaultColDef, defaultRowSelection } from '../common/table-config';
1717
import MultiChipCellRenderer from '../common/multi-chip-cell-renderer';
18+
import { useTableSelection } from 'utils/hooks';
1819

1920
export interface GroupsTableProps {
2021
gridRef: RefObject<GridTableRef<GroupInfos>>;
@@ -26,18 +27,13 @@ const GroupsTable: FunctionComponent<GroupsTableProps> = (props) => {
2627
const intl = useIntl();
2728
const { snackError } = useSnackMessage();
2829

29-
const [rowsSelection, setRowsSelection] = useState<GroupInfos[]>([]);
30+
const { rowsSelection, onSelectionChanged } = useTableSelection<GroupInfos>();
3031
const [showDeletionDialog, setShowDeletionDialog] = useState(false);
3132

3233
function getRowId(params: GetRowIdParams<GroupInfos>): string {
3334
return params.data.name;
3435
}
3536

36-
const onSelectionChanged = useCallback(
37-
(event: SelectionChangedEvent<GroupInfos, {}>) => setRowsSelection(event.api.getSelectedRows() ?? []),
38-
[setRowsSelection]
39-
);
40-
4137
const onAddButton = useCallback(() => props.setOpenAddGroupDialog(true), [props]);
4238

4339
const deleteGroups = useCallback((): Promise<void> | undefined => {

src/pages/profiles/profiles-table.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,12 @@ import { useIntl } from 'react-intl';
1010
import { ManageAccounts } from '@mui/icons-material';
1111
import { GridButton, GridButtonDelete, GridTable, GridTableRef } from '../../components/Grid';
1212
import { UserAdminSrv, UserProfile } from '../../services';
13-
import {
14-
ColDef,
15-
GetRowIdParams,
16-
ITooltipParams,
17-
RowClickedEvent,
18-
SelectionChangedEvent,
19-
TextFilterParams,
20-
} from 'ag-grid-community';
13+
import { ColDef, GetRowIdParams, ITooltipParams, RowClickedEvent, TextFilterParams } from 'ag-grid-community';
2114
import { useSnackMessage } from '@gridsuite/commons-ui';
2215
import DeleteConfirmationDialog from '../common/delete-confirmation-dialog';
2316
import { defaultColDef, defaultRowSelection } from '../common/table-config';
2417
import ValidityCellRenderer from './validity-cell-renderer';
18+
import { useTableSelection } from 'utils/hooks';
2519

2620
export interface ProfilesTableProps {
2721
gridRef: RefObject<GridTableRef<UserProfile>>;
@@ -33,18 +27,13 @@ const ProfilesTable: FunctionComponent<ProfilesTableProps> = (props) => {
3327
const intl = useIntl();
3428
const { snackError } = useSnackMessage();
3529

36-
const [rowsSelection, setRowsSelection] = useState<UserProfile[]>([]);
30+
const { rowsSelection, onSelectionChanged } = useTableSelection<UserProfile>();
3731
const [showDeletionDialog, setShowDeletionDialog] = useState(false);
3832

3933
function getRowId(params: GetRowIdParams<UserProfile>): string {
4034
return params.data.id ?? '';
4135
}
4236

43-
const onSelectionChanged = useCallback(
44-
(event: SelectionChangedEvent<UserProfile, {}>) => setRowsSelection(event.api.getSelectedRows() ?? []),
45-
[setRowsSelection]
46-
);
47-
4837
const onAddButton = useCallback(() => props.setOpenAddProfileDialog(true), [props]);
4938

5039
const deleteProfiles = useCallback(() => {

src/pages/users/users-table.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ import {
1515
GetRowIdParams,
1616
ICheckboxCellRendererParams,
1717
RowClickedEvent,
18-
SelectionChangedEvent,
1918
TextFilterParams,
2019
} from 'ag-grid-community';
2120
import { useSnackMessage } from '@gridsuite/commons-ui';
2221
import DeleteConfirmationDialog from '../common/delete-confirmation-dialog';
2322
import { defaultColDef, defaultRowSelection } from '../common/table-config';
2423
import MultiChipCellRenderer from '../common/multi-chip-cell-renderer';
24+
import { useTableSelection } from 'utils/hooks';
2525

2626
export interface UsersTableProps {
2727
gridRef: RefObject<GridTableRef<UserInfos>>;
@@ -33,18 +33,13 @@ const UsersTable: FunctionComponent<UsersTableProps> = (props) => {
3333
const intl = useIntl();
3434
const { snackError } = useSnackMessage();
3535

36-
const [rowsSelection, setRowsSelection] = useState<UserInfos[]>([]);
36+
const { rowsSelection, onSelectionChanged } = useTableSelection<UserInfos>();
3737
const [showDeletionDialog, setShowDeletionDialog] = useState(false);
3838

3939
function getRowId(params: GetRowIdParams<UserInfos>): string {
4040
return params.data.sub ?? '';
4141
}
4242

43-
const onSelectionChanged = useCallback(
44-
(event: SelectionChangedEvent<UserInfos, {}>) => setRowsSelection(event.api.getSelectedRows() ?? []),
45-
[setRowsSelection]
46-
);
47-
4843
const onAddButton = useCallback(() => props.setOpenAddUserDialog(true), [props]);
4944

5045
const deleteUsers = useCallback(() => {

src/utils/hooks.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8+
import { SelectionChangedEvent } from "ag-grid-community";
9+
import { useCallback, useState } from "react";
10+
811
export function useDebugRender(label: string) {
912
// uncomment when you want the output in the console
1013
/*if (import.meta.env.DEV) {
@@ -13,3 +16,24 @@ export function useDebugRender(label: string) {
1316
console.timeStamp?.(label);
1417
}*/
1518
}
19+
20+
/**
21+
* Custom hook to handle table row selection with proper filtering support
22+
* @returns Selection state and handler for AG Grid's onSelectionChanged
23+
*/
24+
export function useTableSelection<T>() {
25+
const [rowsSelection, setRowsSelection] = useState<T[]>([]);
26+
27+
const onSelectionChanged = useCallback((event: SelectionChangedEvent<T, {}>) => {
28+
// Get only selected rows that are currently visible (after filtering)
29+
const visibleSelectedRows: T[] = [];
30+
event.api.forEachNodeAfterFilterAndSort((node) => {
31+
if (node.isSelected() && node.data) {
32+
visibleSelectedRows.push(node.data);
33+
}
34+
});
35+
setRowsSelection(visibleSelectedRows);
36+
}, []);
37+
38+
return { rowsSelection, setRowsSelection, onSelectionChanged };
39+
}

0 commit comments

Comments
 (0)