---
product: "AG Grid"
title: "Row Grouping - Grouping Data"
description: "Enable row grouping in the Vue Data Grid to allow rows to be grouped by columns. Define row groups, use the Grid API, or use the UI to group rows."
enterprise: true
framework: vue
version: "36.2.0"
related:
    - title: "Overview"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping/"
    - title: "Group Display Types"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping-display-types/"
    - title: "Row Group Panel"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping-group-panel/"
    - title: "Expanding Groups"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping-opening-groups/"
    - title: "Hierarchy Selection"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping-row-selection/"
    - title: "Sorting"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping-sorting/"
    - title: "Editing Groups"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping-edit/"
    - title: "Row Dragging"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping-row-dragging/"
llms: "https://www.ag-grid.com/archive/36.2.0/llms.txt"
---

# Row Grouping - Grouping Data

Enable grouping on a column to group rows by equivalent values.

## Enabling Row Grouping

Row Grouping is enabled by setting `rowGroup` to `true` on one or more [Column Definition](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/column-definitions/). Parent rows are then introduced for each unique value in that column, containing the rows with that value.

#### Basic Grouping

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import { RowGroupingModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, RowGroupingModule]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :autoGroupColumnDef="autoGroupColumnDef"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "country", rowGroup: true, hide: true },
      { field: "year" },
      { field: "athlete" },
      { field: "sport" },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    const autoGroupColumnDef = ref<AutoGroupColumnDef>({
      minWidth: 200,
    });
    const rowData = ref<IOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => (rowData.value = data);

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      autoGroupColumnDef,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Basic Grouping](https://www.ag-grid.com/archive/36.2.0/examples/grouping-data/basic-grouping/vue3/)

The example above uses the following configuration to group rows by their `country` values:

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    { field: 'country', rowGroup: true },
    // ...other column definitions
];
```

## Grouping by Multiple Columns

When grouping on multiple columns using `rowGroup`, the order of columns within the column definitions is used to determine which column to group by first. This can be overridden with a custom order by providing the `rowGroupIndex` property in each grouped columns definition.

#### Grouping by Multiple Columns

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import { RowGroupingModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, RowGroupingModule]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :autoGroupColumnDef="autoGroupColumnDef"
      :groupDefaultExpanded="groupDefaultExpanded"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "country", rowGroupIndex: 1, hide: true },
      { field: "year", rowGroupIndex: 0, hide: true },
      { field: "athlete" },
      { field: "sport" },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    const autoGroupColumnDef = ref<AutoGroupColumnDef>({
      minWidth: 200,
    });
    const groupDefaultExpanded = ref(1);
    const rowData = ref<IOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => (rowData.value = data);

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      autoGroupColumnDef,
      groupDefaultExpanded,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Grouping by Multiple Columns](https://www.ag-grid.com/archive/36.2.0/examples/grouping-data/row-group-index/vue3/)

The example above demonstrates the following configuration for grouping rows by `year` first, and `country` second:

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    { field: 'country', rowGroupIndex: 1 },
    { field: 'year', rowGroupIndex: 0 },
    // ...other column definitions
];
```

## Grouping on Object Data

When grouping on object data, the grid needs a way to compare items to determine if they are equivalent. Setting a `keyCreator` on the grouped column definition provides the grid with string keys it can compare.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `keyCreator` | `KeyCreatorFunc` |  |  |  |

The following example uses a custom set of rows, each containing an `athlete` field that maps to objects with `id` and `name` properties.

#### Grouping by Object Data

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import { RowGroupingModule } from "ag-grid-enterprise";
import { getData } from "./data";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, RowGroupingModule]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :autoGroupColumnDef="autoGroupColumnDef"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "athlete",
        rowGroup: true,
        hide: true,
        // `value` can be `null`/`undefined` for group and footer rows, which have no athlete object.
        keyCreator: (params) => params.value?.id ?? "",
        valueFormatter: (params) => params.value?.name ?? "",
      },
      { field: "country" },
      { field: "year" },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    const autoGroupColumnDef = ref<AutoGroupColumnDef>({
      minWidth: 200,
    });
    const rowData = ref<any[] | null>(getData());

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      autoGroupColumnDef,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Grouping by Object Data](https://www.ag-grid.com/archive/36.2.0/examples/grouping-data/grouping-object-data/vue3/)

This demonstrates the following configuration for grouping rows by the `athlete` objects by their `id` property:

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    {
        field: 'athlete',
        rowGroup: true,
        // params.value is undefined for group rows, so check before reading `id`/`name`
        keyCreator: (params) => params.value?.id ?? '',
        valueFormatter: (params) => params.value?.name ?? '',
    },
    // ...other column definitions
];
```

`keyCreator` and `valueFormatter` are called for group rows as well as leaf rows. A group row has no row `data` of its own, so `params.value` is `undefined` there even for the grouped column itself. See [TypeScript Generics](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/typescript-generics/) for how typing these callbacks' params surfaces this case at compile time.

## Grouping by Dates and Times

When grouping by date/time values, the grid can optionally group by components of the date/time.

To enable grouping by parts of the date for a particular column, use the `groupHierarchy` property of the [Column Definition](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/column-properties/#reference-grouping-groupHierarchy).

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `groupHierarchy` | `(GroupHierarchyParts \| string \| ColDef)[]` |  |  |  |

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    {
        field: 'date',
        rowGroup: true,
        groupHierarchy: ['year', 'month']
    },
    // ...other column definitions
];
```

This snippet is illustrated in the example below.

#### Grouping by Dates and Times

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  SideBarDef,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnsToolPanelModule,
  PivotModule,
  RowGroupingModule,
  RowGroupingPanelModule,
  SideBarModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  RowGroupingModule,
  SideBarModule,
  ColumnsToolPanelModule,
  RowGroupingPanelModule,
  PivotModule,
]);

const COL_DEFS: ColDef<IOlympicData>[] = [
  {
    field: "date",
    rowGroup: true,
    enableRowGroup: true,
    enablePivot: true,
    groupHierarchy: ["year", "month"],
    minWidth: 120,
  },
  { field: "country" },
  { field: "sport" },
  { field: "total", aggFunc: "sum" },
];

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <label style="margin-bottom: 1rem">
        <input id="formatted-month-checkbox" type="checkbox" v-on:change="onChangeFormattedMonth($event)">
          <span>Use formatted month</span>
        </label>
        <ag-grid-vue
          style="width: 100%; height: 100%;"
          @grid-ready="onGridReady"
          :columnDefs="columnDefs"
          :defaultColDef="defaultColDef"
          :autoGroupColumnDef="autoGroupColumnDef"
          :sideBar="sideBar"
          :rowGroupPanelShow="rowGroupPanelShow"
          :rowData="rowData"></ag-grid-vue>
        </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>(COL_DEFS);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    const autoGroupColumnDef = ref<AutoGroupColumnDef>({
      minWidth: 225,
    });
    const sideBar = ref<SideBarDef | string | string[] | boolean | null>(
      "columns",
    );
    const rowGroupPanelShow = ref<"always" | "onlyWhenGrouping" | "never">(
      "always",
    );
    const rowData = ref<IOlympicData[]>(null);

    function onChangeFormattedMonth(event: any) {
      const month = event.target.checked ? "formattedMonth" : "month";
      COL_DEFS[0].groupHierarchy![1] = month;
      gridApi.value.setGridOption("columnDefs", COL_DEFS);
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) =>
        (rowData.value = data.map((d) => ({
          ...d,
          date: d.date?.split("/").reverse().join("-"),
        })));

      fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      autoGroupColumnDef,
      sideBar,
      rowGroupPanelShow,
      rowData,
      onGridReady,
      onChangeFormattedMonth,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Grouping by Dates and Times](https://www.ag-grid.com/archive/36.2.0/examples/grouping-data/grouping-date-time/vue3/)

> **Note**
>
> By default, the grid requires datetime values to be formatted using the ISO-8601 format in order to be correctly parsed into their components.
>
> To use other date formats, provide a custom [Cell Data Type Definition](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/cell-data-types/#providing-custom-cell-data-types) for the `dateString` and/or `dateTimeString` data types.

## Defining Custom Grouping Hierarchies

When using `groupHierarchy` as demonstrated in [Grouping by Dates and Times](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping-data/#grouping-by-dates-and-times), the grid provides built-in support for several components of a date/time value.

Users may instead provide definitions of their own components via the `groupHierarchyConfig` grid option. These definitions may then be used in the `groupHierarchy` property of a column definition.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `groupHierarchyConfig` | `GroupHierarchyConfig` |  |  |  |

The following example illustrates this by defining a custom grouping hierarchy component that allows grouping by the week number:

#### Grouping by Dates and Times

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  ColumnApiModule,
  GridApi,
  GridOptions,
  GridReadyEvent,
  GroupHierarchyConfig,
  ModuleRegistry,
  SideBarDef,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnsToolPanelModule,
  PivotModule,
  RowGroupingModule,
  RowGroupingPanelModule,
  SideBarModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  RowGroupingModule,
  SideBarModule,
  ColumnsToolPanelModule,
  RowGroupingPanelModule,
  ColumnApiModule,
  PivotModule,
]);

function getDate(value: any): Date | null {
  if (value instanceof Date) {
    return value;
  }
  if (typeof value === "string") {
    const [year, month, day] = value.split("-");
    const d = new Date();
    d.setFullYear(parseInt(year, 10), parseInt(month, 10), parseInt(day, 10));
    d.setHours(0, 0, 0, 0);
    return d;
  }
  return null;
}

function getWeekNumber(date: Date): number {
  const d = new Date(date.getTime());
  d.setHours(0, 0, 0, 0);
  d.setDate(d.getDate() + 3 - ((date.getDay() + 6) % 7));
  const week1 = new Date(d.getFullYear(), 0, 4);
  return (
    1 +
    Math.round(
      ((d.getTime() - week1.getTime()) / 86400000 -
        3 +
        ((week1.getDay() + 6) % 7)) /
        7,
    )
  );
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :autoGroupColumnDef="autoGroupColumnDef"
      :sideBar="sideBar"
      :rowGroupPanelShow="rowGroupPanelShow"
      :groupHierarchyConfig="groupHierarchyConfig"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "date",
        rowGroup: true,
        enableRowGroup: true,
        enablePivot: true,
        groupHierarchy: ["year", "week"],
        minWidth: 120,
      },
      { field: "country" },
      { field: "sport" },
      { field: "total", aggFunc: "sum" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    const autoGroupColumnDef = ref<AutoGroupColumnDef>({
      minWidth: 225,
    });
    const sideBar = ref<SideBarDef | string | string[] | boolean | null>(
      "columns",
    );
    const rowGroupPanelShow = ref<"always" | "onlyWhenGrouping" | "never">(
      "always",
    );
    const groupHierarchyConfig = ref<GroupHierarchyConfig>({
      week: {
        headerValueGetter: (params) => {
          const sourceCol = params.api
            .getColumns()
            ?.find((col) => col.getColDef().field === "date");
          if (!sourceCol) return "";
          const name = params.api.getDisplayNameForColumn(
            sourceCol,
            params.location,
          );
          return `${name} (Week)`;
        },
        valueGetter: (params) => {
          const sourceCol = params.api
            .getColumns()
            ?.find((col) => col.getColDef().field === "date");
          const field = sourceCol?.getColDef().field;
          if (!field) return;
          const value = params.getValue(field);
          const date = getDate(value);
          if (!date) return;
          return getWeekNumber(date).toString();
        },
      },
    });
    const rowData = ref<IOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) =>
        (rowData.value = data.map((d) => ({
          ...d,
          date: d.date?.split("/").reverse().join("-"),
        })));

      fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      autoGroupColumnDef,
      sideBar,
      rowGroupPanelShow,
      groupHierarchyConfig,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Grouping by Dates and Times](https://www.ag-grid.com/archive/36.2.0/examples/grouping-data/grouping-custom-date-time/vue3/)

## Grouping on Null and Undefined Data

When grouping `null`, `undefined` or `""` (empty string) values the grid will group these together under the heading `(Blanks)` as the final group.

By setting the `groupAllowUnbalanced` property to `true`, the grid will instead display these rows without a group.

#### Grouping by Null and Undefined Data

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import { RowGroupingModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, RowGroupingModule]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div class="example-header">
        <label>
          <span>groupAllowUnbalanced:</span>
          <input id="groupAllowUnbalanced" type="checkbox" v-on:change="toggleGroupAllowUnbalanced()">
          </label>
        </div>
        <ag-grid-vue
          style="width: 100%; height: 100%;"
          @grid-ready="onGridReady"
          :columnDefs="columnDefs"
          :defaultColDef="defaultColDef"
          :autoGroupColumnDef="autoGroupColumnDef"
          :rowData="rowData"></ag-grid-vue>
        </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "country", rowGroup: true, hide: true },
      { field: "year" },
      { field: "athlete" },
      { field: "sport" },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    const autoGroupColumnDef = ref<AutoGroupColumnDef>({
      minWidth: 200,
    });
    const rowData = ref<IOlympicData[]>(null);

    function toggleGroupAllowUnbalanced() {
      const enable = document.querySelector<HTMLInputElement>(
        "#groupAllowUnbalanced",
      )!.checked;
      gridApi.value.setGridOption("groupAllowUnbalanced", enable);
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => (rowData.value = data);

      fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      autoGroupColumnDef,
      rowData,
      onGridReady,
      toggleGroupAllowUnbalanced,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Grouping by Null and Undefined Data](https://www.ag-grid.com/archive/36.2.0/examples/grouping-data/grouping-null-undefined/vue3/)

To enable unbalanced grouping, the following configuration is used:

```ts
<ag-grid-vue
    :groupAllowUnbalanced="groupAllowUnbalanced"
    /* other grid options ... */>
</ag-grid-vue>

this.groupAllowUnbalanced = true;
```

## Hiding Parents of Individual Rows

Groups with only a single child can be hidden from the grid by setting the `groupHideParentOfSingleChild` grid option to `true`. To remove only groups with a single leaf child, set this option to `"leafGroupsOnly"` instead.

Filtering does not impact which groups get removed. Only groups containing a single child prior to filtering being applied are removed.

#### Removing Single Children

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { getData } from "./data";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  RowGroupingModule,
  SetFilterModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div class="example-header">
        <label>
          <span>groupHideParentOfSingleChild:</span>
          <select id="input-display-type" v-on:change="onOptionChange()">
            <option value="false">false</option>
            <option value="true">true</option>
            <option value="leafGroupsOnly">"leafGroupsOnly"</option>
          </select>
        </label>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :autoGroupColumnDef="autoGroupColumnDef"
        :rowData="rowData"
        :groupDefaultExpanded="groupDefaultExpanded"
        :suppressAggFuncInHeader="true"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete" },
      { field: "country", rowGroup: true },
      { field: "city", rowGroup: true },
      { field: "year" },
      { field: "gold", aggFunc: "sum" },
      { field: "silver", aggFunc: "sum" },
      { field: "bronze", aggFunc: "sum" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 150,
    });
    const autoGroupColumnDef = ref<AutoGroupColumnDef>({
      headerName: "Group",
      field: "athlete",
      minWidth: 220,
      cellRenderer: "agGroupCellRenderer",
    });
    const rowData = ref<any[] | null>(getData());
    const groupDefaultExpanded = ref(-1);

    function onOptionChange() {
      const key = (
        document.querySelector("#input-display-type") as HTMLSelectElement
      ).value;
      if (key === "true" || key === "false") {
        gridApi.value!.setGridOption(
          "groupHideParentOfSingleChild",
          key === "true",
        );
      } else {
        gridApi.value!.setGridOption(
          "groupHideParentOfSingleChild",
          "leafGroupsOnly",
        );
      }
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      autoGroupColumnDef,
      rowData,
      groupDefaultExpanded,
      onGridReady,
      onOptionChange,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Removing Single Children](https://www.ag-grid.com/archive/36.2.0/examples/grouping-data/remove-single-children/vue3/)

The following is an example of the configuration used to hide all parents of a single row:

```ts
<ag-grid-vue
    :groupHideParentOfSingleChild="groupHideParentOfSingleChild"
    /* other grid options ... */>
</ag-grid-vue>

this.groupHideParentOfSingleChild = true;
```

> **Note**
>
> The properties `groupHideParentOfSingleChild` and `groupHideOpenParents` are mutually exclusive.
