---
title: "Tree Data - Group Column"
enterprise: true
framework: react
version: "36.1.0"
---

# Tree Data - Group Column

Customise the generated group column when using Tree Data.

## Group Column Configuration

When using Tree Data, the grid will automatically generate a group column to display the hierarchy. This column can be configured by using the `autoGroupColumnDef` grid option, allowing any [Column Property](https://www.ag-grid.com/react-data-grid/column-definitions/) to be overridden.

#### Group Column Configuration

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GetDataPath,
  GridApi,
  GridOptions,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import { TreeDataModule } from "ag-grid-enterprise";
import { getData } from "./data";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [ClientSideRowModelModule, TreeDataModule];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [rowData, setRowData] = useState<any[]>(getData());
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "created" },
    { field: "modified" },
    {
      field: "size",
      aggFunc: "sum",
      valueFormatter: (params) => {
        const sizeInKb = params.value / 1024;
        if (sizeInKb > 1024) {
          return `${+(sizeInKb / 1024).toFixed(2)} MB`;
        } else {
          return `${+sizeInKb.toFixed(2)} KB`;
        }
      },
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
    };
  }, []);
  const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
    return {
      headerName: "My Group",
      minWidth: 340,
    };
  }, []);
  const getDataPath = useCallback((data) => data.path, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact
            rowData={rowData}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            autoGroupColumnDef={autoGroupColumnDef}
            treeData={true}
            groupDefaultExpanded={-1}
            getDataPath={getDataPath}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Group Column Configuration](https://www.ag-grid.com/examples/tree-data-group-column/group-column/reactFunctionalTs)

The example above sets different header text and a minimum width to each Group Column cell using the following configuration:

```jsx
const autoGroupColumnDef = useMemo(() => { 
	return {
        headerName: 'My Group',
        minWidth: 220,
    };
}, []);

<AgGridReact autoGroupColumnDef={autoGroupColumnDef} />
```

## Group Cell Component

The grid uses the `agGroupCellRenderer` component to render the group column cells.

### Child Row Counts

When showing child counts with Tree Data, the child count is a count of all descendants, including groups.

#### Child Counts

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GetDataPath,
  GridApi,
  GridOptions,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import { TreeDataModule } from "ag-grid-enterprise";
import { getData } from "./data";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [ClientSideRowModelModule, TreeDataModule];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [rowData, setRowData] = useState<any[]>(getData());
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "created" },
    { field: "modified" },
    {
      field: "size",
      aggFunc: "sum",
      valueFormatter: (params) => {
        const sizeInKb = params.value / 1024;
        if (sizeInKb > 1024) {
          return `${+(sizeInKb / 1024).toFixed(2)} MB`;
        } else {
          return `${+sizeInKb.toFixed(2)} KB`;
        }
      },
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
    };
  }, []);
  const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
    return {
      headerName: "File Explorer",
      minWidth: 270,
    };
  }, []);
  const getDataPath = useCallback((data) => data.path, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact
            rowData={rowData}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            autoGroupColumnDef={autoGroupColumnDef}
            treeData={true}
            groupDefaultExpanded={-1}
            getDataPath={getDataPath}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Child Counts](https://www.ag-grid.com/examples/tree-data-group-column/child-counts/reactFunctionalTs)

Note how in the example above, the `Desktop` row has a child count of 5, of which one of is the `ProjectAlpha` [Filler Group](https://www.ag-grid.com/react-data-grid/tree-data-paths/#filler-groups) row.

### Default Component Options

The options configurable on the `agGroupCellRenderer` via the column definition `cellRendererParams` are:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `suppressPadding` | `boolean` |  |  | Set to `true` to not include any padding (indentation) in the child rows. |
| `suppressDoubleClickExpand` | `boolean` |  |  | Set to `true` to suppress expand on double click. |
| `suppressEnterExpand` | `boolean` |  |  | Set to `true` to suppress expand on ↵ Enter |
| `totalValueGetter` | `string \| TotalValueGetterFunc` |  |  | The value getter for the total row text. Can be a function or expression. |
| `suppressCount` | `boolean` |  |  | If `true`, count is not displayed beside the name. |
| `innerRenderer` | `any` |  |  | The renderer to use for inside the cell (after grouping functions are added) |
| `innerRendererParams` | `any` |  |  | Additional params to customise to the `innerRenderer`. |
| `innerRendererSelector` | `CellRendererSelectorFunc` |  |  | Callback to enable different innerRenderers to be used based of value of params. |

### Custom Component

Where the default `agGroupCellRenderer` does not meet your requirements, you can provide a [Custom Cell Component](https://www.ag-grid.com/react-data-grid/component-cell-renderer/), via the `cellRenderer` property in the `autoGroupColumnDef` grid option.

The below example provides a custom cell renderer which:

- Uses a custom icon to represent the groups expanded state
- Responds to row expansion events to update if the group is expanded or collapsed from another source
- Cleans up all event listeners when it's destroyed

#### Custom Component

```tsx
'use client';
import React, { StrictMode, useCallback, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";

import type {
  CellDoubleClickedEvent,
  CellKeyDownEvent,
  ColDef,
} from "ag-grid-community";
import {
  ClientSideRowModelModule,
  enableDevValidations,
} from "ag-grid-community";
import { TreeDataModule } from "ag-grid-enterprise";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import CustomGroupCellRenderer from "./customGroupCellRenderer";
import { getData } from "./data";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [ClientSideRowModelModule, TreeDataModule];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "created" },
    { field: "modified" },
    {
      field: "size",
      aggFunc: "sum",
      valueFormatter: (params) => {
        const sizeInKb = params.value / 1024;

        if (sizeInKb > 1024) {
          return `${+(sizeInKb / 1024).toFixed(2)} MB`;
        } else {
          return `${+sizeInKb.toFixed(2)} KB`;
        }
      },
    },
  ]);
  const autoGroupColumnDef = useMemo<ColDef>(() => {
    return {
      cellRenderer: CustomGroupCellRenderer,
    };
  }, []);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 120,
    };
  }, []);

  const getDataPath = useCallback((data: any) => data.path, []);

  const onCellDoubleClicked = useCallback((params: CellDoubleClickedEvent) => {
    if (params.colDef.showRowGroup) {
      params.node.setExpanded(!params.node.expanded);
    }
  }, []);

  const onCellKeyDown = useCallback((params: CellKeyDownEvent) => {
    if (!("colDef" in params)) {
      return;
    }
    if (!(params.event instanceof KeyboardEvent)) {
      return;
    }
    if (params.event.code !== "Enter") {
      return;
    }
    if (params.colDef.showRowGroup) {
      params.node.setExpanded(!params.node.expanded);
    }
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact
            treeData
            getDataPath={getDataPath}
            rowData={getData()}
            columnDefs={columnDefs}
            autoGroupColumnDef={autoGroupColumnDef}
            defaultColDef={defaultColDef}
            groupDefaultExpanded={1}
            onCellDoubleClicked={onCellDoubleClicked}
            onCellKeyDown={onCellKeyDown}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Custom Component](https://www.ag-grid.com/examples/tree-data-group-column/custom-component/reactFunctionalTs)

This demonstrates supplying a custom cell renderer via the `cellRenderer` property in the `autoGroupColumnDef`:

```jsx
const autoGroupColumnDef = useMemo(() => { 
	return {
        cellRenderer: CellRenderer,
    };
}, []);

<AgGridReact autoGroupColumnDef={autoGroupColumnDef} />
```

### Dynamic Component Selection

When it's necessary to use different renderers in the same column, you can configure this with the `cellRendererSelector` property in the `autoGroupColumnDef` grid option.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `cellRendererSelector` | `CellRendererSelectorFunc` |  |  | Callback to select which cell renderer to be used for a given row within the same column. |

The example below extends the [Custom Component](https://www.ag-grid.com/react-data-grid/tree-data-group-column/#custom-component) example to use a different renderer based on the rows level:

#### Dynamic Component Selection

```tsx
'use client';
import React, { StrictMode, useCallback, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";

import type {
  CellDoubleClickedEvent,
  CellKeyDownEvent,
  ColDef,
} from "ag-grid-community";
import {
  ClientSideRowModelModule,
  enableDevValidations,
} from "ag-grid-community";
import { TreeDataModule } from "ag-grid-enterprise";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import CustomGroupCellRenderer from "./customGroupCellRenderer";
import { getData } from "./data";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [ClientSideRowModelModule, TreeDataModule];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "created" },
    { field: "modified" },
    {
      field: "size",
      aggFunc: "sum",
      valueFormatter: (params) => {
        const sizeInKb = params.value / 1024;

        if (sizeInKb > 1024) {
          return `${+(sizeInKb / 1024).toFixed(2)} MB`;
        } else {
          return `${+sizeInKb.toFixed(2)} KB`;
        }
      },
    },
  ]);
  const autoGroupColumnDef = useMemo<ColDef>(() => {
    return {
      cellRendererSelector: (params) => {
        if (params.node.level === 0) {
          return {
            component: "agGroupCellRenderer",
          };
        }
        return {
          component: CustomGroupCellRenderer,
        };
      },
    };
  }, []);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 120,
    };
  }, []);

  const getDataPath = useCallback((data: any) => data.path, []);

  const onCellDoubleClicked = useCallback((params: CellDoubleClickedEvent) => {
    if (params.colDef.showRowGroup) {
      params.node.setExpanded(!params.node.expanded);
    }
  }, []);

  const onCellKeyDown = useCallback((params: CellKeyDownEvent) => {
    if (!("colDef" in params)) {
      return;
    }
    if (!(params.event instanceof KeyboardEvent)) {
      return;
    }
    if (params.event.code !== "Enter") {
      return;
    }
    if (params.node.level === 0) {
      return;
    }
    if (params.colDef.showRowGroup) {
      params.node.setExpanded(!params.node.expanded);
    }
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact
            treeData
            getDataPath={getDataPath}
            rowData={getData()}
            columnDefs={columnDefs}
            autoGroupColumnDef={autoGroupColumnDef}
            defaultColDef={defaultColDef}
            groupDefaultExpanded={1}
            onCellDoubleClicked={onCellDoubleClicked}
            onCellKeyDown={onCellKeyDown}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Dynamic Component Selection](https://www.ag-grid.com/examples/tree-data-group-column/dynamic-component/reactFunctionalTs)

This uses the following configuration to display the default cell renderer for root level groups, and the custom renderer for all others:

```jsx
const cellRendererSelector = (params) => {
    if (params.node.level === 0) {
        return {
            component: 'agGroupCellRenderer',
        };
    }
    return {
        component: CustomGroupCellRenderer,
    };
};

<AgGridReact cellRendererSelector={cellRendererSelector} />
```

Refer to the [Cell Components](https://www.ag-grid.com/react-data-grid/component-cell-renderer/) documentation for information on how to create custom cell renderers.
