---
title: "Auto-Generate Columns"
framework: javascript
version: "36.1.0"
---

# Auto-Generate Columns

Column definitions can be generated automatically from `rowData`, without defining them upfront. This is useful when working with dynamic or unknown data shapes.

Set `autoGenerateColumnDefs` to `true` and the grid scans `rowData` for the first non-null row, then creates a column for each of its keys:

#### Auto-Generate Columns

```ts
import {
  AutoGenerateColumnsModule,
  ClientSideRowModelModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  AutoGenerateColumnsModule,
]);

let gridApi: GridApi;

const gridOptions: GridOptions = {
  autoGenerateColumnDefs: true,
  rowData: [
    {
      name: "Alice",
      address: { city: "London", country: "UK" },
      scores: { maths: 92, science: 88 },
    },
    {
      name: "Bob",
      address: { city: "Paris", country: "France" },
      scores: { maths: 75, science: 91 },
    },
    {
      name: "Charlie",
      address: { city: "Berlin", country: "Germany" },
      scores: { maths: 84, science: 79 },
    },
    {
      name: "Diana",
      address: { city: "Madrid", country: "Spain" },
      scores: { maths: 96, science: 85 },
    },
    {
      name: "Eve",
      address: { city: "Rome", country: "Italy" },
      scores: { maths: 68, science: 94 },
    },
  ],
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);
```

[Live example: Auto-Generate Columns](https://www.ag-grid.com/examples/auto-generate-columns/nested-objects/typescript)

```js
const gridOptions = {
    autoGenerateColumnDefs: true,
    rowData: myData,
};
```

## Column Generation

The grid scans `rowData` for the first non-null row and creates columns based on value types:

- **Primitive values** (strings, numbers, booleans, bigints, Date instances) — a leaf column.
- **Plain objects** — a column group by default, with nested keys recursed into. The `headerName` is derived from the key name.
- **Arrays** — a leaf column if the first element is a primitive value; skipped if the array is empty or contains objects. Arrays render as a comma-separated string.
- **null/undefined values** — a leaf column by default.
- **Functions** — skipped.

For example, given this row data:

```js
rowData: [
    { user: { name: 'Alice', age: 30 }, score: 100 },
]
```

The generated column definitions are:

```js
columnDefs: [
    {
        headerName: 'User',
        children: [
            { field: 'user.name', headerName: 'Name' },
            { field: 'user.age', headerName: 'Age' },
        ],
    },
    { field: 'score' },
]
```

> **Note**
>
> Row data keys containing dots (e.g. `"user.name"`) are treated as nested paths by default. Set `suppressFieldDotNotation` to `true` to treat dotted keys as literal field names. See [Accessing Row Data Values](https://www.ag-grid.com/javascript-data-grid/value-getters/#field) for details.

Column groups are only produced when the value for a key in the first scanned row is a non-empty plain object, with the default `objectValues: 'group'`. Arrays, primitives, dates, class instances and empty objects all yield leaf columns or are skipped. Ensure `rowData` has the nested structure you expect before relying on generated group headers.

## Configuration

Pass an `AutoGenerateColumnDefsOptions` object instead of `true` to control how each value type is handled. The example below lets you toggle each option to see how it affects the generated columns:

#### Configuration

```ts
import {
  AutoGenerateColumnDefsOptions,
  AutoGenerateColumnsModule,
  ClientSideRowModelModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  AutoGenerateColumnsModule,
]);

let gridApi: GridApi;

const config: AutoGenerateColumnDefsOptions = {
  objectValues: "group",
  arrayValues: "primitives",
  nullishValues: "include",
};

const rowData = [
  {
    name: "Alice",
    age: 32,
    address: { city: "London", country: "UK" },
    roles: ["admin", "user"],
    notes: null,
  },
  {
    name: "Bob",
    age: 28,
    address: { city: "Paris", country: "France" },
    roles: ["user"],
    notes: null,
  },
  {
    name: "Charlie",
    age: 35,
    address: { city: "Berlin", country: "Germany" },
    roles: ["admin"],
    notes: null,
  },
  {
    name: "Diana",
    age: 24,
    address: { city: "Madrid", country: "Spain" },
    roles: ["user", "moderator"],
    notes: null,
  },
  {
    name: "Eve",
    age: 29,
    address: { city: "Rome", country: "Italy" },
    roles: ["admin", "moderator"],
    notes: null,
  },
];

const gridOptions: GridOptions = {
  autoGenerateColumnDefs: { ...config },
  rowData,
};

function onObjectValues(): void {
  const value = (document.getElementById("objectValues") as HTMLSelectElement)
    .value;
  config.objectValues = value as AutoGenerateColumnDefsOptions["objectValues"];
  gridApi.setGridOption("autoGenerateColumnDefs", { ...config });
}

function onArrayValues(): void {
  const value = (document.getElementById("arrayValues") as HTMLSelectElement)
    .value;
  config.arrayValues = value as AutoGenerateColumnDefsOptions["arrayValues"];
  gridApi.setGridOption("autoGenerateColumnDefs", { ...config });
}

function onNullishValues(): void {
  const value = (document.getElementById("nullishValues") as HTMLSelectElement)
    .value;
  config.nullishValues =
    value as AutoGenerateColumnDefsOptions["nullishValues"];
  gridApi.setGridOption("autoGenerateColumnDefs", { ...config });
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).onObjectValues = onObjectValues;
  (<any>window).onArrayValues = onArrayValues;
  (<any>window).onNullishValues = onNullishValues;
}
```

[Live example: Configuration](https://www.ag-grid.com/examples/auto-generate-columns/configuration/typescript)

Properties available on the `AutoGenerateColumnDefsOptions` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `objectValues` | `'group' \| 'flatten' \| 'skip'` |  | `'group'` | How to handle plain-object values. `'group'` recurses into the object and creates a column group, `'flatten'` recurses and creates flat leaf columns using dotted field paths, `'skip'` ignores the field entirely. |
| `arrayValues` | `'primitives' \| 'include' \| 'skip'` |  | `'primitives'` | How to handle array values. `'primitives'` creates a leaf column only when the first element is a primitive value, `'include'` creates a leaf column for all arrays, `'skip'` ignores them. |
| `nullishValues` | `'include' \| 'skip'` |  | `'include'` | How to handle `null` and `undefined` values. `'include'` creates a leaf column, `'skip'` ignores them. |

Setting `objectValues` to `'flatten'` produces top-level columns with dotted field paths instead of nested groups:

```js
// Row data: { name: 'Alice', address: { city: 'London' } }
// With objectValues: 'flatten':
columnDefs: [
    { field: 'name' },
    { field: 'address.city', headerName: 'City' },
]
```

## Updating Row Data

Columns are regenerated each time `rowData` is set. Only the keys from the first non-null row are used, so columns update when the data shape changes.

By default, column order matches the key order of that first row. Set `maintainColumnOrder` to `true` to preserve existing column positions when the data shape changes:

```js
const gridOptions = {
    autoGenerateColumnDefs: true,
    maintainColumnOrder: true,
};
```

See [Maintain Column Order](https://www.ag-grid.com/javascript-data-grid/column-updating-definitions/#maintain-column-order) for details.

Setting `rowData` to `[]` clears both the rows and the column definitions.

> **Note**
>
> Updating data via transactions (`applyTransaction` / `applyTransactionAsync`) does not trigger column generation.

## Customising Generated Columns

[Default Column Definitions](https://www.ag-grid.com/javascript-data-grid/column-definitions/#default-column-definitions) apply to auto-generated columns the same way as manually defined ones. This is the simplest way to set common properties like filtering or resizing.

For per-column customisation, use the `processAutoGeneratedColumnDefs` callback to modify, reorder, or replace columns before they are applied. The callback receives `params.columnDefs` (which may include `ColGroupDef` entries when row data contains nested objects) and `params.rowData`, and returns the final `(ColDef | ColGroupDef)[]`.

Use `forEachColDef` to mutate leaf column properties without having to handle group recursion yourself:

```js
import { forEachColDef } from 'ag-grid-community';

const gridOptions = {
    autoGenerateColumnDefs: true,
    rowData: myData,
    processAutoGeneratedColumnDefs: ({ columnDefs }) => {
        forEachColDef(columnDefs, (colDef) => {
            colDef.hide = colDef.field === 'internalId';
        });
        // Add a custom column
        columnDefs.push({ headerName: 'Actions', cellRenderer: ActionsRenderer });
        return columnDefs;
    },
};
```

The example below uses [Column Types](https://www.ag-grid.com/javascript-data-grid/column-definitions/#column-types) to apply a `currencyColumn` type to any column whose field contains `"profit"`:

#### Customising Columns

```ts
import {
  AutoGenerateColumnsModule,
  ClientSideRowModelModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  ProcessAutoGeneratedColumnDefs,
  createGrid,
  enableDevValidations,
  forEachColDef,
} from "ag-grid-community";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  AutoGenerateColumnsModule,
  NumberFilterModule,
]);

let gridApi: GridApi;

const processAutoGeneratedColumnDefs: ProcessAutoGeneratedColumnDefs = (
  params,
) => {
  forEachColDef(params.columnDefs, (colDef) => {
    if (colDef.field?.includes("profit")) {
      colDef.type = "currencyColumn";
    }
  });
  return params.columnDefs;
};

const gridOptions: GridOptions = {
  autoGenerateColumnDefs: true,
  columnTypes: {
    currencyColumn: {
      valueFormatter: (params) =>
        params.value == null ? "" : "£" + params.value.toLocaleString(),
      filter: "agNumberColumnFilter",
    },
  },
  processAutoGeneratedColumnDefs,
  defaultColDef: {
    flex: 1,
  },
  rowData: [
    { product: "Widget A", region: "North", profit: 12500, profitMargin: 0.15 },
    { product: "Widget B", region: "South", profit: 8300, profitMargin: 0.11 },
    { product: "Gadget X", region: "East", profit: 21000, profitMargin: 0.22 },
    { product: "Gadget Y", region: "West", profit: 5600, profitMargin: 0.08 },
    { product: "Gizmo Z", region: "North", profit: 17400, profitMargin: 0.19 },
  ],
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);
```

[Live example: Customising Columns](https://www.ag-grid.com/examples/auto-generate-columns/customising-columns/typescript)

## File Drop Overlay

When `autoGenerateColumnDefs` is enabled and no `rowData` is present, a file drop overlay is shown automatically when `processFileInput` is provided. Files can be dragged onto the overlay or selected via a browse button. See [Overlays](https://www.ag-grid.com/javascript-data-grid/overlays-overview/) for more on grid overlays.

Provide a `processFileInput` callback. The `params` object contains the selected `files` array along with `success` and `fail` callbacks. Call `success(rowData)` to load the parsed data into the grid, or `fail(message)` to display an error in the overlay using the `fileInputProcessingFailed` locale.

`params.files` contains every file the user dropped or selected. The example below processes the first file only; iterate over `params.files` to handle multiple files.

```js
const gridOptions = {
    autoGenerateColumnDefs: true,
    processFileInput: (params) => {
        const file = params.files[0];
        const reader = new FileReader();
        reader.onload = (e) => {
            try {
                const rowData = parseCsv(e.target.result);
                params.success(rowData);
            } catch {
                params.fail('Failed to parse file');
            }
        };
        reader.readAsText(file);
    },
};
```

The example below auto-generates columns from various data sources. Files can be dragged onto the overlay, selected via the browse button, or loaded from the sample data dropdown. The toolbar **Upload File** button re-shows the overlay by setting `activeOverlay` to `'agFileInputOverlay'`.

#### Auto-Generate Columns

```ts
import {
  AutoGenerateColumnsModule,
  ClientSideRowModelModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  ProcessFileInputParams,
  TextFilterModule,
  ToolbarItemActionParams,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { ToolbarModule } from "ag-grid-enterprise";

declare let XLSX: any;

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  AutoGenerateColumnsModule,
  TextFilterModule,
  NumberFilterModule,
  ToolbarModule,
]);

let gridApi: GridApi;

function parseWorkbook(workbook: any): Record<string, unknown>[] {
  const firstSheetName = workbook.SheetNames[0];
  const worksheet = workbook.Sheets[firstSheetName];
  return XLSX.utils.sheet_to_json(worksheet);
}

function processFileInput(params: ProcessFileInputParams): void {
  const file = params.files[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onerror = () => {
    params.fail("Failed to read file");
  };
  reader.onload = (e) => {
    try {
      const workbook = XLSX.read(
        new Uint8Array(e.target?.result as ArrayBuffer),
      );
      params.success(parseWorkbook(workbook));
    } catch (error) {
      console.error(error);
      params.fail("Failed to parse file");
    }
  };
  reader.readAsArrayBuffer(file);
}

const gridOptions: GridOptions = {
  autoGenerateColumnDefs: true,
  processFileInput: processFileInput,
  defaultColDef: {
    minWidth: 80,
    flex: 1,
  },
  toolbar: {
    items: [
      {
        label: "Upload File",
        icon: "document",
        alignment: "right",
        action: (params: ToolbarItemActionParams) => {
          const curr = params.api.getGridOption("activeOverlay");
          params.api.setGridOption(
            "activeOverlay",
            curr === "agFileInputOverlay" ? undefined : "agFileInputOverlay",
          );
        },
      },
    ],
  },
};

function onLoadSampleData(): void {
  const select = document.getElementById("sampleData") as HTMLSelectElement;
  const value = select.value;
  if (!value) return;

  if (value.endsWith(".xlsx")) {
    fetch(`https://www.ag-grid.com/example-assets/${value}`)
      .then((response) => response.arrayBuffer())
      .then((data: ArrayBuffer) => {
        const workbook = XLSX.read(new Uint8Array(data));
        gridApi.updateGridOptions({
          activeOverlay: undefined,
          rowData: parseWorkbook(workbook),
        });
      });
  } else {
    fetch(`https://www.ag-grid.com/example-assets/${value}`)
      .then((response) => response.json())
      .then((rows) => {
        gridApi.updateGridOptions({ activeOverlay: undefined, rowData: rows });
      });
  }
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).onLoadSampleData = onLoadSampleData;
}
```

[Live example: Auto-Generate Columns](https://www.ag-grid.com/examples/auto-generate-columns/file-drop-overlay/typescript)
