Description
DataGrid Checkbox Nested Group Intermediate Select
Functionality + Select All
Functionality
I found your snippets extremely useful, but I noticed it broke in cases where nested groups were used. It also didn't allow the "select all" header to work properly.
Code below:
- Allows selecting groups by checkbox - including nested groups
- Applies the Table's
filter
andsort
settings to the selected rows - Adds the same nested group selection ability to the "Select All" column header checkbox.
const checkboxColumn = (
apiRef: MutableRefObject<GridApiPremium>
): GridColDef => {
return {
...GRID_CHECKBOX_SELECTION_COL_DEF,
renderHeader: (params) => {
const children = gridFilteredSortedRowIdsSelector(
apiRef.current.state,
apiRef.current.instanceId
).filter((id) => !id.toString().includes("auto-generated"));
const selectionLookup = selectedIdsLookupSelector(
apiRef.current.state,
apiRef.current.instanceId
);
const indeterminate =
children?.some((child) => selectionLookup[child] === undefined) &&
children?.some((child) => selectionLookup[child] !== undefined);
const checked = children?.every(
(child) => selectionLookup[child] !== undefined
);
const data: GridColumnHeaderParams & {
indeterminate?: boolean;
checked?: boolean;
disabled?: boolean;
onClick?: (e: MouseEvent) => void;
} = {
...params,
onClick: (e) => {
apiRef.current.selectRows(children, indeterminate || !checked);
e.preventDefault();
},
indeterminate,
checked,
};
return (
<>
<GridHeaderCheckbox {...data} />
</>
);
},
renderCell: (params) => {
const { rowNode } = params;
if (rowNode.type !== "group")
return <GridCellCheckboxRenderer {...params} />;
const selectionLookup = selectedIdsLookupSelector(
apiRef.current.state,
apiRef.current.instanceId
);
const children = apiRef.current.getRowGroupChildren({
groupId: rowNode.id,
applyFiltering: true,
applySorting: true,
});
const indeterminate =
children?.some((child) => selectionLookup[child] === undefined) &&
children?.some((child) => selectionLookup[child] !== undefined);
const checked = children?.every(
(child) => selectionLookup[child] !== undefined
);
const extraData: GridRenderCellParams &
GridRenderCellParamsPremium & {
indeterminate?: boolean;
checked?: boolean;
disabled?: boolean;
onClick?: (e: MouseEvent) => void;
} = {
...params,
disabled: false,
onClick: (e) => {
if (rowNode.groupingField != null) {
if (children) {
apiRef.current.selectRows(children, indeterminate || !checked);
}
e.preventDefault();
}
},
indeterminate,
checked,
};
return <GridCellCheckboxRenderer {...extraData} />;
},
};
};
export default checkboxColumn;
It is making use of the GridApi for fetching group children (and subgroup's children) with the apiRef.current.getRowGroupChildren
, which includes grandchildren by default. This method also automatically filters out autogenerated group row IDs. It accepts the applyFiltering: true, applySorting: true
props which ensure the row selection applies only to the rows that haven't been filtered, in their sort-order.
The code added to the renderHeader
prop allows the "Select All" checkbox to basically function the same as the group checkboxes, only it cannot make use of the apiRef.current.getRowGroupChildren
method because that method takes a group row's id as a parameter. Unfortunately, this means we have to again manually filter out the group row IDs.
Originally posted by @cclews1 in #4248 (comment)
Search keywords: