Skip to content

[data grid] Checkbox Nested Group Intermediate Select Functionality + Select All Functionality #13036

Open
@mtsmith

Description

@mtsmith

DataGrid Checkbox Nested Group Intermediate Select Functionality + Select All Functionality

@nickcarnival @cstephens-cni

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 and sort 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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    component: data gridThis is the name of the generic UI component, not the React module!enhancementThis is not a bug, nor a new featurefeature: SelectionRelated to the data grid Selection featurefeature: Tree dataRelated to the data grid Tree data feature

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions