---
title: "Column Menu"
enterprise: true
framework: javascript
version: "36.1.0"
---

# Column Menu

The column menu is launched from the grid header, and displays a list of menu items, along with the ability to select columns and display filters.

> **Note**
>
> AG Grid Community does not have a menu, but can launch [Column Filters](https://www.ag-grid.com/javascript-data-grid/filtering/) if enabled (see [Launching Filters](https://www.ag-grid.com/javascript-data-grid/filter-api/#launching-filters) for configuration details).

The following example shows the column menu:

- The **Athlete** column does not have filtering enabled, and only shows the main menu.
- The **Age** column has filtering enabled, and shows an additional filter icon. Open and apply a filter to see the behaviour.
- The **Country** column has filtering enabled with the floating filter. Open and apply a filter to see the behaviour.
- Right-clicking on the column headers will also display the column menu.
- Right-clicking in the empty space to the right of the column headers will display the column menu with options to choose/reset the columns.

#### Column Menu

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  ColumnAutoSizeModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  CalculatedColumnsModule,
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  CalculatedColumnsModule,
  TextFilterModule,
  NumberFilterModule,
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  ColumnAutoSizeModule,
]);

const columnDefs: ColDef[] = [
  { field: "athlete", minWidth: 200 },
  { field: "age", filter: true },
  { field: "country", filter: true, floatingFilter: true, minWidth: 200 },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: columnDefs,
  defaultColDef: {
    minWidth: 100,
  },
  calculatedColumns: true,
};

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

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Column Menu](https://www.ag-grid.com/examples/column-menu/column-menu/typescript)

## Customising the Column Menu

How the column menu is launched from the header can be configured via the following column definition properties.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `suppressHeaderMenuButton` | `boolean` |  | `false` | Set to `true` if no menu button should be shown for this column header. |
| `suppressHeaderFilterButton` | `boolean` |  | `false` | Set to `true` to not display the filter button in the column header. Doesn't apply when `columnMenu = 'legacy'`. |
| `suppressHeaderContextMenu` | `boolean` |  | `false` | Set to `true` to not display the column menu when the column header is right-clicked. Doesn't apply when `columnMenu = 'legacy'`. |

The following example demonstrates different ways of customising the column menu:

- The **Athlete** column has a filter and the menu button suppressed, but still available via right-click.
- The **Age** column has a floating filter and the menu suppressed, but still available via right-click.
- The **Country** column has a filter and the header filter button suppressed.
- The **Year** column has a floating filter and the header filter button suppressed.
- The **Sport** column has no filter and the menu suppressed on right-click.
- The **Gold** column has no filter and the menu button suppressed, but still available via right-click
- The **Silver** column has a filter (with the header filter button suppressed), and the menu button suppressed but still available via right-click.
- The **Bronze** column has a floating filter and the menu button suppressed, but still available via right-click.
- The **Total** column has the menu button, header filter button and right-click menu suppressed.

#### Customising the Column Menu

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  CalculatedColumnsModule,
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  CalculatedColumnsModule,
  TextFilterModule,
  NumberFilterModule,
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
]);

const columnDefs: ColDef[] = [
  {
    field: "athlete",
    minWidth: 200,
    filter: true,
    suppressHeaderMenuButton: true,
  },
  {
    field: "age",
    filter: true,
    floatingFilter: true,
    suppressHeaderMenuButton: true,
  },
  {
    field: "country",
    minWidth: 200,
    filter: true,
    suppressHeaderFilterButton: true,
  },
  {
    field: "year",
    filter: true,
    floatingFilter: true,
    suppressHeaderFilterButton: true,
  },
  { field: "sport", minWidth: 200, suppressHeaderContextMenu: true },
  {
    field: "gold",
    suppressHeaderMenuButton: true,
    suppressHeaderFilterButton: true,
  },
  {
    field: "silver",
    filter: true,
    suppressHeaderMenuButton: true,
    suppressHeaderFilterButton: true,
  },
  {
    field: "bronze",
    filter: true,
    floatingFilter: true,
    suppressHeaderMenuButton: true,
    suppressHeaderFilterButton: true,
  },
  {
    field: "total",
    filter: true,
    suppressHeaderMenuButton: true,
    suppressHeaderFilterButton: true,
    suppressHeaderContextMenu: true,
  },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: columnDefs,
  defaultColDef: {
    flex: 1,
    minWidth: 100,
  },
  calculatedColumns: true,
};

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

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Customising the Column Menu](https://www.ag-grid.com/examples/column-menu/customising-column-menu/typescript)

## Customising the Menu Items

The menu shows a default set of items. You can add your own items, or change which defaults are shown, via two independent properties - use whichever suits, or both:

- `colDef.columnMenuItems` - set per column. Either a list of menu items, or a callback which is passed the list of default items.
- `getColumnMenuItems()` - a grid option callback which is passed the list of default items, the column, and the `source` of the menu.

When both are set, `colDef.columnMenuItems` takes priority over `getColumnMenuItems()`.

The `source` param is one of `'columnMenu'`, `'columnsToolPanel'` or `'columnChooser'`, so a single callback can tailor the items for the column menu, the [Columns Tool Panel](https://www.ag-grid.com/javascript-data-grid/tool-panel-columns/#context-menu) context menu, and the [Column Chooser](#customising-the-column-chooser).

Each item is either a string or a `MenuItemDef`. Use a string to pick a built-in item and a `MenuItemDef` for your own. All built-in tokens share one type, `DefaultColumnMenuItem`, and each is shown only where it applies to the column and grid state. The column menu's [built-in items](#built-in-menu-items) are listed below.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `columnMenuItems` | `(DefaultColumnMenuItem \| MenuItemDef)[] \| GetColumnMenuItems` |  |  | Customise the menu items shown for this column across the column menu, the Columns Tool Panel right-click menu, and the Column Chooser. The `source` param indicates which surface the menu is for. Takes precedence over `mainMenuItems`. Modules (any of): [`ColumnMenuModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`ColumnsToolPanelModule`](https://www.ag-grid.com/javascript-data-grid/modules/). |

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getColumnMenuItems` | `GetColumnMenuItems` |  |  | For customising the menu items shown for a column across the column menu, the Columns Tool Panel right-click menu, and the Column Chooser. The `source` param indicates which surface the menu is for; branch on it to target a single surface. Takes precedence over `getMainMenuItems` for the column menu. Modules (any of): [`ColumnMenuModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`ColumnsToolPanelModule`](https://www.ag-grid.com/javascript-data-grid/modules/). [Initial](https://www.ag-grid.com/javascript-data-grid/grid-interface/#initial-grid-options). |

### Legacy Column Menu Properties

`colDef.mainMenuItems` and the grid option `getMainMenuItems()` are the original way to customise the menu. They behave the same way, but apply to the column menu only - not the Columns Tool Panel or Column Chooser - and their callbacks do not receive a `source`. Prefer `columnMenuItems` / `getColumnMenuItems()`; these older properties remain supported and take effect when the newer ones are not set.

The full order of precedence is `colDef.columnMenuItems`, then `getColumnMenuItems()`, then `colDef.mainMenuItems`, then `getMainMenuItems()`. A grid-level `getColumnMenuItems()` therefore takes precedence over a per-column `mainMenuItems`.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `mainMenuItems` | `(DefaultMenuItem \| MenuItemDef)[] \| GetMainMenuItems` |  |  | Customise the list of menu items available in the column menu. Module: [`ColumnMenuModule`](https://www.ag-grid.com/javascript-data-grid/modules/). |

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getMainMenuItems` | `GetMainMenuItems` |  |  | For customising the main 'column header' menu. Module: [`ColumnMenuModule`](https://www.ag-grid.com/javascript-data-grid/modules/). [Initial](https://www.ag-grid.com/javascript-data-grid/grid-interface/#initial-grid-options). |

### Built-In Menu Items

The following is a list of all the default built-in menu items with the rules about when they are shown.

- `sortAscending`: Sort the column in ascending order. Not shown when `columnMenu = 'legacy'` or the column is already sorted in ascending order.
- `sortDescending`: Sort the column in descending order. Not shown when `columnMenu = 'legacy'` or the column is already sorted in descending order.
- `sortUnSort`: Clear the sort on the column. Not shown when `columnMenu = 'legacy'` or the column is not sorted.
- `calculatedColumn`: Show the Calculated Columns options. If the column selected is a Calculated Column, the menu will show options to edit and remove the column.
- `editColumnName`: Rename the column header. Only shown when `headerNameEditable` is set on the column, and never on a calculated column, which is renamed via its **Edit Calculated Column** dialog instead.
- `columnFilter`: Show the column filter. Not shown when `columnMenu = 'legacy'`, a filter is not enabled, or the header filter button or floating filter button are displayed.
- `columnChooser`: Show the column chooser. Not shown when `columnMenu = 'legacy'`.
- `pinSubMenu`: Sub-menu for pinning. Always shown.
- `valueAggSubMenu`: Sub-menu for value aggregation. Always shown.
- `autoSizeThis`: Auto-size the current column. Always shown.
- `autoSizeAll`: Auto-size all columns. Always shown.
- `rowGroup`: Group by this column. Only shown if column is not grouped. Note this will appear once there is row grouping.
- `rowUnGroup`: Un-group by this column. Only shown if column is grouped. Note this will appear once there is row grouping.
- `resetColumns`: Reset column details. Always shown.
- `expandAll`: Expand all groups. Only shown if grouping by at least one column.
- `contractAll`: Collapse all groups. Only shown if grouping by at least one column.

The `defaultItems` list will change on different calls, depending on, for example, which columns are currently used for grouping.

If you do not override the list of menu items, then the items displayed will be based on the rules above.

[Columns Tool Panel](https://www.ag-grid.com/javascript-data-grid/tool-panel-columns/#context-menu) tokens such as `value` can also be returned here, and are shown where they apply to the column.

### Menu Item Separators

Menu items can be grouped together by adding separators between groups. Separators are defined by the string value `'separator'`. For example, you could add menu item separators as follows:

```js
menuItems.push('separator')
```

### Custom Menu Item Components

In addition to the provided menu items, it is also possible to create custom menu item components.

For more details, refer to the section: [Custom Menu Item Components](https://www.ag-grid.com/javascript-data-grid/component-menu-item/).

### Example: Customising the Menu Items

The following example demonstrates the `colDef.columnMenuItems` property:

- The **Athlete** column shows the list of built-in items.
- The **Age** column includes the `value` token before its custom items. The grid is grouped by **Sport**, so **Add Age to values** aggregates Age in the group rows.
- The **Country** column provides two custom items and one built-in item, **Reset Columns** (`resetColumns`). Clicking a custom item logs to the developer console.
- The **Year** column keeps the default items but removes the separators, the pinning sub-menu, and the value aggregation sub-menu.

#### Customising the Menu Items

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  DefaultColumnMenuItem,
  GetColumnMenuItemsParams,
  GridApi,
  GridOptions,
  MenuItemDef,
  ModuleRegistry,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  RowGroupingModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

const columnDefs: ColDef[] = [
  { field: "athlete", minWidth: 200 },
  {
    field: "age",
    enableValue: true,
    minWidth: 150,
    columnMenuItems: (params: GetColumnMenuItemsParams) => {
      // 'value' is a Columns Tool Panel token; it resolves on the column menu too.
      const menuItems: (DefaultColumnMenuItem | MenuItemDef)[] = [
        "value",
        "separator",
        ...params.defaultItems,
        {
          name: "A Custom Item",
          action: () => {
            console.log("A Custom Item selected");
          },
        },
        {
          name: "Custom Sub Menu",
          subMenu: [
            {
              name: "Black",
              action: () => {
                console.log("Black was pressed");
              },
            },
            {
              name: "White",
              action: () => {
                console.log("White was pressed");
              },
            },
            {
              name: "Grey",
              action: () => {
                console.log("Grey was pressed");
              },
            },
          ],
        },
      ];
      return menuItems;
    },
  },
  {
    field: "country",
    minWidth: 200,
    columnMenuItems: [
      {
        // our own item with an icon
        name: "A Custom Item",
        action: () => {
          console.log("A Custom Item selected");
        },
        icon: '<img src="https://www.ag-grid.com/example-assets/lab.png" style="width: 14px;" />',
      },
      {
        // our own icon with a check box
        name: "Another Custom Item",
        action: () => {
          console.log("Another Custom Item selected");
        },
        checked: true,
      },
      "resetColumns", // a built in item
    ],
  },
  {
    field: "year",
    columnMenuItems: (params: GetColumnMenuItemsParams) => {
      const menuItems: (DefaultColumnMenuItem | MenuItemDef)[] = [];
      const itemsToExclude = ["separator", "pinSubMenu", "valueAggSubMenu"];
      params.defaultItems.forEach((item) => {
        if (itemsToExclude.indexOf(item) < 0) {
          menuItems.push(item);
        }
      });
      return menuItems;
    },
  },
  { field: "sport", minWidth: 200, rowGroup: true, enableRowGroup: true },
  { field: "gold" },
  { field: "silver" },
  { field: "bronze" },
  { field: "total" },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: columnDefs,
  autoGroupColumnDef: {
    minWidth: 330,
  },
  defaultColDef: {
    flex: 1,
    minWidth: 100,
  },
};

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

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Customising the Menu Items](https://www.ag-grid.com/examples/column-menu/customising-menu-items/typescript)

## Customising the Column Chooser

The behaviour and appearance of the Columns Menu tab can be customised by supplying `ColumnChooserParams` to the column definition: `colDef.columnChooserParams`. Note that all of the properties are initially set to `false`.

Properties available on the `ColumnChooserParams` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `suppressSyncLayoutWithGrid` | `boolean` |  |  | To suppress updating the layout of columns as they are rearranged in the grid |
| `suppressColumnFilter` | `boolean` |  |  | To suppress Column Filter section |
| `suppressColumnSelectAll` | `boolean` |  |  | To suppress Select / Un-select all widget |
| `suppressColumnExpandAll` | `boolean` |  |  | To suppress Expand / Collapse all widget |
| `contractColumnSelection` | `boolean` |  |  | By default, column groups start expanded. Pass true to default to contracted groups |
| `columnLayout` | `(ColDef \| ColGroupDef)[]` |  |  | Custom Columns Panel layout |

The following example demonstrates all of the above column chooser properties **except columnLayout** which will be covered later on. Note the following:

- Launch the column chooser by selecting `Choose Columns` from any of the column menus.
- The column chooser when launched from any column has been configured to ignore column moves in the grid by setting `suppressSyncLayoutWithGrid=true` on the default column definition.
- The **Name** column chooser doesn't show the top filter section as `suppressColumnFilter`, `suppressColumnSelectAll` and `suppressColumnExpandAll` are all set to `true`.
- The **Age** column chooser shows the group columns in a collapsed state as `contractColumnSelection` is set to `true`.

#### Customising Column Chooser

```ts
import {
  ClientSideRowModelModule,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

const columnDefs: ColGroupDef[] = [
  {
    groupId: "athleteGroupId",
    headerName: "Athlete",
    children: [
      {
        headerName: "Name",
        field: "athlete",
        minWidth: 200,
        columnChooserParams: {
          // hides the Column Filter section
          suppressColumnFilter: true,

          // hides the Select / Un-select all widget
          suppressColumnSelectAll: true,

          // hides the Expand / Collapse all widget
          suppressColumnExpandAll: true,
        },
      },
      {
        field: "age",
        minWidth: 200,
        columnChooserParams: {
          // contracts all column groups
          contractColumnSelection: true,
        },
      },
    ],
  },
  {
    groupId: "medalsGroupId",
    headerName: "Medals",
    children: [{ field: "gold" }, { field: "silver" }, { field: "bronze" }],
  },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: columnDefs,
  defaultColDef: {
    flex: 1,
    columnChooserParams: {
      // suppresses updating the layout of columns as they are rearranged in the grid
      suppressSyncLayoutWithGrid: true,
    },
  },
};

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

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Customising Column Chooser](https://www.ag-grid.com/examples/column-menu/customising-column-chooser/typescript)

### Custom Column Layout

By default the order of columns in the column chooser is derived from the `columnDefs` supplied in the grid options, and is kept in sync with the grid when columns are moved.

However, a custom column layout can be provided using the **columnLayout** property in the `colDef.columnChooserParams`.

```js
const gridOptions = {
    // original column definitions supplied to the grid
    columnDefs: [
        {
            columnChooserParams: {
                columnLayout: [{
                    headerName: 'Group 1', // group doesn't appear in grid
                    children: [
                        { field: 'c' }, // custom column order with column "b" omitted
                        { field: 'a' }
                    ]
                }]
            }
        },
        { field: 'b' },
        { field: 'c' }
    ],

    // other grid options ...
}
```

> **Note**
>
> When providing a custom columns layout by setting the **columnLayout** property, the `suppressSyncLayoutWithGrid` property will automatically set to true. This means that reordering the columns in the grid will not reorder the columns in the list shown in columns menu tab.

The following example demonstrates providing custom column layouts in the column chooser via the **columnLayout** property. Note the following:

- Open the column chooser for the **Name** column and note it shows the custom column order as specified in its `columnLayout`.
- Open the column chooser for the **Age** column and note it shows the actual column order shown in the grid.
- Reorder columns in the grid - drag the **Age** column and drop it on the left of the **Name** column.
- Open the column chooser for the **Age** column and note that the column layout now shows the **Age** column before the **Name** column.
- Open the column chooser for the **Name** column and note that the column layout still shows the **Name** column followed by the **Age** column (custom column layout is not synchronized with the grid column order).

#### Customising Columns Layout

```ts
import {
  ClientSideRowModelModule,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

const columnDefs: ColGroupDef[] = [
  {
    groupId: "athleteGroupId",
    headerName: "Athlete",
    children: [
      {
        headerName: "Name",
        field: "athlete",
        minWidth: 150,
        columnChooserParams: {
          columnLayout: [
            {
              headerName: "Group 1", // Athlete group renamed to "Group 1"
              children: [
                // custom column order with columns "gold", "silver", "bronze" omitted
                { field: "sport" },
                { field: "athlete" },
                { field: "age" },
              ],
            },
          ],
        },
      },
      {
        field: "age",
        minWidth: 120,
      },
      {
        field: "sport",
        minWidth: 150,
        columnChooserParams: {
          // contracts all column groups
          contractColumnSelection: true,
        },
      },
    ],
  },
  {
    groupId: "medalsGroupId",
    headerName: "Medals",
    children: [{ field: "gold" }, { field: "silver" }, { field: "bronze" }],
  },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: columnDefs,
  defaultColDef: {
    flex: 1,
  },
};

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

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Customising Columns Layout](https://www.ag-grid.com/examples/column-menu/customising-columns-layout/typescript)

## Column Menu API / Events

The `gridApi` has the following methods that can be used to interact with the column menu:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `showColumnChooser` | `Function` |  |  | Show the column chooser. Module: [`ColumnMenuModule`](https://www.ag-grid.com/javascript-data-grid/modules/). |
| `showColumnMenu` | `Function` |  |  | Show the column menu for the provided column. |
| `hidePopupMenu` | `Function` |  |  | Hides any visible [Context Menu](https://www.ag-grid.com/javascript-data-grid/context-menu/) or [Column Menu](https://www.ag-grid.com/javascript-data-grid/column-menu/). |
| `hideColumnChooser` | `Function` |  |  | Hide the column chooser if visible. Module: [`ColumnMenuModule`](https://www.ag-grid.com/javascript-data-grid/modules/). |

Column filters are not considered part of the menu, so have their own API methods to show/hide.

However, when using the [Legacy Tabbed Column Menu](#legacy-tabbed-column-menu), the filter popup is part of the column menu, and can be opened/closed via the column menu API methods.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `showColumnFilter` | `Function` |  |  | Show the filter for the provided column. Modules (any of): [`TextFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`NumberFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`DateFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`SetFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`MultiFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`CustomFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/). |
| `hideColumnFilter` | `Function` |  |  | Hide the filter popup if it is open. Modules (any of): [`TextFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`NumberFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`DateFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`SetFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`MultiFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/), [`CustomFilterModule`](https://www.ag-grid.com/javascript-data-grid/modules/). |

The following column menu event is emitted by the grid. Note that this also includes the column filter popup.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `columnMenuVisibleChanged` | `ColumnMenuVisibleChangedEvent` |  |  | The column menu visibility has changed. Fires twice if switching between tabs - once with the old tab and once with the new tab. |

The following example demonstrates the column menu API and events (by clicking the buttons outside the grid).

Note that the column menu and column filter popup close automatically when clicking outside the grid, so there are no buttons to close them in the example.

#### Column Menu API

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  ColumnMenuVisibleChangedEvent,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  CalculatedColumnsModule,
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  CalculatedColumnsModule,
  TextFilterModule,
  NumberFilterModule,
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
]);

const columnDefs: ColDef[] = [
  { field: "athlete", minWidth: 200 },
  { field: "age" },
  { field: "country", minWidth: 200 },
  { field: "year" },
  { field: "sport", minWidth: 200 },
  { field: "gold" },
  { field: "silver" },
  { field: "bronze" },
  { field: "total" },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: columnDefs,
  defaultColDef: {
    flex: 1,
    minWidth: 100,
    filter: true,
  },
  calculatedColumns: true,
  onColumnMenuVisibleChanged: (event: ColumnMenuVisibleChangedEvent) => {
    console.log("columnMenuVisibleChanged", event);
  },
};

function showColumnChooser() {
  gridApi.showColumnChooser();
}

function showColumnFilter(colKey: string) {
  gridApi.showColumnFilter(colKey);
}

function showColumnMenu(colKey: string) {
  gridApi.showColumnMenu(colKey);
}

function hideColumnChooser() {
  gridApi.hideColumnChooser();
}

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

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));

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

[Live example: Column Menu API](https://www.ag-grid.com/examples/column-menu/column-menu-api/typescript)

## Menu Popup

The column menu is displayed inside a popup, which can be further configured.

### Repositioning the Popup

If not happy with the position of the popup, you can override its position using the `postProcessPopup(params)` callback. This gives you the popup HTML element so you can change its position should you wish to.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `postProcessPopup` | `PostProcessPopup` |  |  | Allows user to process popups after they are created. Applications can use this if they want to, for example, reposition the popup. |

The following example demonstrates using `postProcessPopup()` to move the **Age** column menu down by 25 pixels.

#### Column Menu Popup

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  PostProcessPopupParams,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

const columnDefs: ColDef[] = [
  { field: "athlete", minWidth: 200 },
  { field: "age" },
  { field: "country", minWidth: 200 },
  { field: "year" },
  { field: "sport", minWidth: 200 },
  { field: "gold" },
  { field: "silver" },
  { field: "bronze" },
  { field: "total" },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: columnDefs,
  defaultColDef: {
    flex: 1,
    minWidth: 100,
  },
  postProcessPopup: (params: PostProcessPopupParams) => {
    // check callback is for menu
    if (params.type !== "columnMenu") {
      return;
    }
    const columnId = params.column ? params.column.getId() : undefined;
    if (columnId === "age") {
      const ePopup = params.ePopup;

      let oldTopStr = ePopup.style.top!;
      // remove 'px' from the string (AG Grid uses px positioning)
      oldTopStr = oldTopStr.substring(0, oldTopStr.indexOf("px"));
      const oldTop = parseInt(oldTopStr);
      const newTop = oldTop + 25;

      ePopup.style.top = newTop + "px";
    }
  },
};

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

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Column Menu Popup](https://www.ag-grid.com/examples/column-menu/column-menu-popup/typescript)

### Popup Parent

Under most scenarios, the menu will fit inside the grid. However if the grid is small and / or the menu is very large, then the menu will not fit inside the grid and it will be clipped. This will lead to a bad user experience.

To fix this, you should set the [Popup Parent](https://www.ag-grid.com/javascript-data-grid/context-menu/#popup-parent) property.

## Legacy Tabbed Column Menu

The menu can also be displayed in the legacy tabbed format with three panels by setting the grid option `columnMenu = 'legacy'`. If you want to change the order in which panels are shown, or hide them, you can specify the property `menuTabs` in the `colDef`.

The property `menuTabs` is an array of strings. The valid values are: `'filterMenuTab'`, `'generalMenuTab'` and `'columnsMenuTab'`.

- `generalMenuTab`: Include to show the main panel.
- `filterMenuTab`: Include to show the filter panel.
- `columnsMenuTab`: Include to show the column chooser panel.

The order of the menu tabs shown in the menu will match the order you specify in this array.

If you don't specify a `menuTabs` for a `colDef` the default is: `['generalMenuTab', 'filterMenuTab', 'columnsMenuTab']`

The following example demonstrates the default tabbed menu:

- The **Athlete** column shows the default tabs.
- The **Age** column changes the order of the tabs to `['filterMenuTab', 'generalMenuTab', 'columnsMenuTab']`
- The **Country** column changes the order of the tabs to `['filterMenuTab', 'columnsMenuTab']`. Note that the `'generalMenuTab'` is suppressed.
- The **Year** column changes the tabs to `['generalMenuTab']`. Note that the `'filterMenuTab'` and `'columnsMenuTab'` are suppressed.
- The **Sport** column hides the menu by suppressing all the menuTabs that can be shown: `[]`.

#### Column Menu

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  ColumnAutoSizeModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  TextFilterModule,
  NumberFilterModule,
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  ColumnAutoSizeModule,
]);

const columnDefs: ColDef[] = [
  { field: "athlete", minWidth: 200 },
  {
    field: "age",
    menuTabs: ["filterMenuTab", "generalMenuTab", "columnsMenuTab"],
  },
  {
    field: "country",
    minWidth: 200,
    menuTabs: ["filterMenuTab", "columnsMenuTab"],
  },
  { field: "year", menuTabs: ["generalMenuTab"] },
  { field: "sport", minWidth: 200, menuTabs: [] },
  { field: "gold" },
  { field: "silver" },
  { field: "bronze" },
  { field: "total" },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: columnDefs,
  defaultColDef: {
    flex: 1,
    minWidth: 100,
    filter: true,
  },
  columnMenu: "legacy",
};

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

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Column Menu](https://www.ag-grid.com/examples/column-menu/column-menu-legacy/typescript)

With the legacy menu, the column menu button is hidden until moused over. This can be changed to always show the button using the grid option `suppressMenuHide`.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `suppressMenuHide` | `boolean` |  | `true` | Only recommended for use if `columnMenu = 'legacy'`. When `true`, the column menu button will always be shown. When `false`, the column menu button will only show when the mouse is over the column header. When using `columnMenu = 'legacy'`, this will default to `false` instead of `true`. |
