---
title: "Tree Data - Self-Referential Records"
enterprise: true
framework: vue
version: "36.1.0"
---

# Tree Data - Self-Referential Records

Configure the grid to display structured data by providing self-referential records where each record contains a reference to the id of its parent. This is the most performant way to provide and update hierarchical data to the grid, as the `rowData` is processed in a single pass.

## Providing Hierarchy

Each row in the data can contain a field containing the id of its parent row. The `treeDataParentIdField` property is used to specify the field containing the parent row id.

The below structure demonstrates a simple hierarchy, wherein the `treeDataParentIdField` grid option would specify `"parentId"` as the field containing the parent row id:

```
const data = [
    { id: 'A' },
    { id: 'B', parentId: 'A' },
    { id: 'C', parentId: 'A' },
    { id: 'D' },
    { id: 'E', parentId: 'D' },
    { id: 'F', parentId: 'E' },
]
```

In the above hierarchy, the 'A' row is the parent of 'B' and 'C'. The 'D' row is the parent of 'E' which is the parent of 'F'.

> **Note**
>
> [getRowId](https://www.ag-grid.com/vue-data-grid/row-ids/#row-ids) callback must be provided when using `treeDataParentIdField` to ensure each row has a unique identifier that can be correctly referenced.

Ensure your data is correctly structured, as cycles and missing parent rows are not allowed.

For example, the following data structure would not be valid as the 'A' row is missing:

```
const data = [
    { id: 'B', parentId: 'A' },
    { id: 'C', parentId: 'A' },
]
```

The following data structure would not be valid as it creates a cycle:

```
const data = [
    { id: 'A', parentId: 'B' },
    { id: 'B', parentId: 'A' },
]
```

## Providing Group Values

When providing a self-referential hierarchy, the grid will use the row ID as the group value by default. To provide a custom value, the field property of the `autoGroupColumnDef` grid option can be used.

The example below demonstrates a case where the `autoGroupColumnDef` field is set to `name` to display a group value:

#### Group Values

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GetRowIdFunc,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import { TreeDataModule } from "ag-grid-enterprise";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([ClientSideRowModelModule, TreeDataModule]);

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"
      :getRowId="getRowId"
      :treeData="true"
      :treeDataParentIdField="treeDataParentIdField"
      :groupDefaultExpanded="groupDefaultExpanded"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "modified",
      },
      {
        field: "created",
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
    });
    const autoGroupColumnDef = ref<AutoGroupColumnDef>({
      headerName: "Name",
      field: "name",
      cellRendererParams: {
        suppressCount: true,
      },
    });
    const rowData = ref<any[] | null>(getData());
    const getRowId = ref<GetRowIdFunc>((params) => params.data.id);
    const treeDataParentIdField = ref("parentId");
    const groupDefaultExpanded = ref(-1);

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

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

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

[Live example: Group Values](https://www.ag-grid.com/examples/tree-data-self-referential/basic-example/vue3)

The following snippet demonstrates how to provide nested siblings with a custom group value:

```ts
<ag-grid-vue
    :treeData="treeData"
    :treeDataParentIdField="treeDataParentIdField"
    :getRowId="getRowId"
    :autoGroupColumnDef="autoGroupColumnDef"
    /* other grid options ... */>
</ag-grid-vue>

this.treeData = true;
this.treeDataParentIdField = 'parentId';
this.getRowId = (params) => params.data.id;
this.autoGroupColumnDef = {
    field: 'name',
};
```

## Supplied vs Aggregated

When using Tree Data, columns defined with an aggregation function will always perform aggregations on the group nodes. This means any supplied group data will be ignored in favour of the aggregated values.

#### Aggregated Data

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GetRowIdFunc,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import { TreeDataModule } from "ag-grid-enterprise";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([ClientSideRowModelModule, TreeDataModule]);

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"
      :getRowId="getRowId"
      :treeData="true"
      :treeDataParentIdField="treeDataParentIdField"
      :groupDefaultExpanded="groupDefaultExpanded"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        headerName: "Aggregated (Sum)",
        aggFunc: "sum",
        field: "items",
      },
      {
        headerName: "Provided",
        field: "items",
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
    });
    const autoGroupColumnDef = ref<AutoGroupColumnDef>({
      headerName: "Name",
      field: "name",
      cellRendererParams: {
        suppressCount: true,
      },
    });
    const rowData = ref<any[] | null>(getData());
    const getRowId = ref<GetRowIdFunc>((params) => params.data.id);
    const treeDataParentIdField = ref("parentId");
    const groupDefaultExpanded = ref(-1);

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

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

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

[Live example: Aggregated Data](https://www.ag-grid.com/examples/tree-data-self-referential/aggregated-data/vue3)

The example above uses the configuration below to demonstrate the `Desktop` row is being aggregated to show the sum of its children (4), rather than the provided value (1), despite both columns showing the same field:

```
const gridOptions = {
    treeData: true,
    columnDefs: [
        {
            headerName: 'Aggregated (Sum)',
            aggFunc: 'sum',
            field: 'items',
        },
        {
            headerName: 'Provided',
            field: 'items',
        },
    ],
};
```

Refer to the [Aggregation](https://www.ag-grid.com/vue-data-grid/aggregation/) page for more details, and [Editing Groups](https://www.ag-grid.com/vue-data-grid/grouping-edit/) for editing aggregated values with cascading updates to children.
