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.
- React
- Angular
- Core TypeScript
<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 }),
}}
/>
<awb-grid
[rowData]="rows"
[columnDefs]="columns"
[rowNumbers]="true"
[rowPinningMenu]="true"
[getColumnMenuItems]="columnMenu"
[bodyContextMenu]="bodyMenu"
[rowInsertionMenu]="insertionMenu"
/>
columnMenu = ({ ctx, items }: ColumnMenuContext) => [
...items,
{ isSeparator: true },
{ id: "inspect-column", label: "Inspect " + ctx.targetColId, onClick: () => this.inspect(ctx) },
];
const options: GridOptions = {
rowNumbers: true,
rowPinningMenu: true,
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 }),
canInsert: ({ data }) => data.locked !== true,
},
};
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.