Skip to main content

Menus

Column menus and the body context menu are configuration, not plumbing: extend, reorder, filter, or replace the items the grid built, and opt into row pinning and row insertion commands.

Loading interactive example…
React
<Grid
rowData={rows}
columnDefs={columns}
rowNumbers
rowPinningMenu
getColumnMenuItems={({ ctx, items }) => [
...items,
{ isSeparator: true },
{
id: "inspect-column",
label: "Inspect " + ctx.targetColId,
onClick: () => inspectColumn(ctx.targetColId),
},
]}
bodyContextMenu={({ ctx, items }) => [
...items,
{ isSeparator: true },
{ id: "open-record", label: "Open record", onClick: () => openRecord(ctx.rowId) },
]}
rowInsertionMenu={{
createRow: ({ data, position }) => ({ ...data, id: nextId(), name: "Inserted " + position }),
}}
/>

Column-menu visibility

const columnDefs: ColDef[] = [
{ key: "name", label: "Name", showColumnMenu: false },
{ key: "city", label: "City", columnContextMenu: false },
{ key: "status", label: "Status", filter: true },
];

const options = {
showColumnButtonsOnHover: true,
} satisfies GridOptions;

showColumnMenu: false hides the button but leaves right-click access. columnContextMenu: false restores the native header context menu but leaves the button. Filterable columns add their filter panel to the menu.

Customize column-menu items

const options = {
getColumnMenuItems: ({ ctx, items }) => [
...items,
{ isSeparator: true },
{
id: "inspect-column",
label: `Inspect ${ctx.targetColId}`,
onClick: () => inspectColumn(ctx.targetColId),
},
],
} satisfies GridOptions;

The callback receives the items the grid built and returns the items to show. In React and Angular, menu items may also carry framework content in their left/right slots.

Body context menu

const options = {
bodyContextMenu: ({ ctx, items }) => [
...items,
{ isSeparator: true },
{
id: "open-record",
label: "Open record",
onClick: () => openRecord(ctx.rowId),
},
],
} satisfies GridOptions;

Use bodyContextMenu: false for the browser's native menu, or return [] to suppress both the grid items and the native menu. Copy, cut, paste, and export commands appear automatically when applicable.

Row pinning menu

const options = {
rowPinningMenu: true,
bodyContextMenu: true,
} satisfies GridOptions;

The body menu adds Pin to top, Pin to bottom, and Unpin for the row or selection — see pinned rows.

Row insertion menu

let nextId = 100;

const options = {
rowNumbers: true,
rowInsertionMenu: {
createRow: ({ data, position }) => ({
...data,
id: String(nextId++),
name: `Inserted ${position}`,
}),
// Optional: hide either direction for a particular row.
canInsert: ({ data, position }) => data.locked !== true || position === "below",
},
} satisfies GridOptions;

This opt-in adds Insert → 1 row above / 1 row below only to row-number context menus on client-side rows. The factory owns required fields and stable IDs. Insertion uses underlying source order, so an active sort or filter may display the new row somewhere else.