fleet/frontend/components/TableContainer/utilities/config_utils.ts
Nico 49463f19e9
Fix select-all header checkbox not selecting rows in a specific case (#40940)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #40789

Seems like on specific pages of server-side paginated tables, the
select-all header checkbox does not work. This happens when:
- the page has less than 20 rows (I think this is the default page size)
- AND not all the rows are selectable

`headerProps.rows` always contains all rows currently visible in the
table. Using rows also keeps the select logic consistent with the
deselect and "all selected" checks, which already used rows.

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [x] QA'd all new/changed functionality manually

### Before

Clicking on the table header checkbox doesn't perform any selection



https://github.com/user-attachments/assets/d5b1f2fc-1400-4f3e-a2b4-2ae6a3da65af

### After



https://github.com/user-attachments/assets/54a67707-7978-40ec-ba50-c146a67795b2
2026-03-04 11:39:04 -03:00

54 lines
1.6 KiB
TypeScript

// from https://stackoverflow.com/a/68213902/15458245
import { HeaderProps, Row } from "react-table";
interface GetConditionalSelectHeaderCheckboxProps {
/** react-table header props */
headerProps: React.PropsWithChildren<HeaderProps<any>>;
checkIfRowIsSelectable: (row: Row<any>) => boolean;
}
export const getConditionalSelectHeaderCheckboxProps = ({
headerProps,
checkIfRowIsSelectable,
}: GetConditionalSelectHeaderCheckboxProps) => {
// Define if the checkbox should show as checked or indeterminate
const checkIfAllSelectableRowsSelected = (rows: Row<any>[]) => {
const selectableRows = rows.filter(checkIfRowIsSelectable);
return (
selectableRows.length > 0 && selectableRows.every((row) => row.isSelected)
);
};
const allSelectableRowsSelected = checkIfAllSelectableRowsSelected(
headerProps.rows
);
const indeterminate =
!allSelectableRowsSelected &&
headerProps.rows.some((row) => row.isSelected);
const onChange = () => {
if (checkIfAllSelectableRowsSelected(headerProps.rows)) {
headerProps.rows.forEach((row) => {
headerProps.toggleRowSelected(row.id, false);
});
} else {
// Otherwise select every selectable row on the page
headerProps.rows.forEach((row) => {
const rowChecked = checkIfRowIsSelectable(row);
headerProps.toggleRowSelected(row.id, rowChecked);
});
}
};
// Usual checkbox props
const checkboxProps = headerProps.getToggleAllRowsSelectedProps();
return {
...checkboxProps,
value: allSelectableRowsSelected,
indeterminate,
onChange,
};
};
export default { getConditionalSelectHeaderCheckboxProps };