Customizing the Cell menu and the Header menu

Bryntum Grid ships with built-in context menus for grid cells and for grid column headers. Right-click a cell or a column header in the demo below to see it in action:

Basic menu
//<code-header>
fiddle.title = 'Basic menu';
//</code-header>
const grid = new Grid({
    appendTo : targetElement,

    autoHeight : true,
    rowHeight  : 50,

    columns : [
        { text : 'Name', field : 'name', width : 160 }
    ],

    data : [
        { id : 1, name : 'Mr Boss' }
    ]
});

The menus can be customized, turned off or replaced with your own implementation (see the "Replace context menus" guide).

Turning the menus off entirely

The menus are supplied by corresponding features: CellMenu feature provides menu for cells, HeaderMenu feature provides menu for column headers. These features are enabled by default. To turn a feature off, configure it with false:

const grid = new Grid({
    features : {
        // Turn the Cell menu off completely, will not be created
        cellMenu : false,
        // Turn the Header menu off completely, will not be created
        headerMenu : false
    }
});

Enabling or disabling the menus

You can also enable or disable any of the provided menus programmatically, perhaps depending on user rights:

const grid = new Grid({
    features : {
        cellMenu : {
            // The Cell menu is created, but starts disabled
            disabled : true
        },
        headerMenu : {
            // The Header menu is created, but starts disabled
            disabled : true
        }
    }
});

// To enable
grid.features.cellMenu.disabled = false;
grid.features.headerMenu.disabled = false;

// To disable again
grid.features.cellMenu.disabled = true;
grid.features.headerMenu.disabled = true;

Try it in the demo below:

Disable menu feature
//<code-header>
fiddle.title = 'Disable menu feature';
//</code-header>
const grid = new Grid({
    appendTo   : targetElement,
    autoHeight : true,
    rowHeight  : 50,
    flex       : 1,

    columns : [
        { text : 'Name', field : 'name', width : 160 }
    ],

    data : [
        { id : 1, name : 'Mr Boss' }
    ],

    features : {
        cellMenu : {
            disabled : true
        },
        headerMenu : {
            disabled : true
        }
    },

    tbar : [
        {
            text        : 'Disable Cell menu',
            toggleable  : true,
            pressed     : true,
            icon        : 'fa fa-square',
            pressedIcon : 'fa fa-check-square',
            onToggle({ pressed }) {
                grid.features.cellMenu.disabled = pressed;
            }
        },
        {
            text        : 'Disable Header menu',
            style       : 'margin-inline-start: 10px',
            toggleable  : true,
            pressed     : true,
            icon        : 'fa fa-square',
            pressedIcon : 'fa fa-check-square',
            onToggle({ pressed }) {
                grid.features.headerMenu.disabled = pressed;
            }
        }
    ]
});

Customizing the menu items

The menu items in the Cell menu and in the Header menu can be customized, existing items can be changed or removed, and new items can be added. This is handled using the items config of the features.

Default cell menu items

The CellMenu feature provides only one item by default and all the other items are populated by the other features:

Item referenceTextWeightFeatureEnabled by defaultDescription
removeRowDelete record100CellMenutrueRemoves the selected record from the store
searchSearch for value200SearchfalseSearches the grid for the selected cell text
filterMenu*Filter400FiltertrueShows a submenu to control filtering. See Filter submenu.
*
items that are generated dynamically

Default header menu items

The Header menu has no default items provided by the HeaderMenu feature, but there are other features that populate the header menu with the following items:

Item referenceTextWeightFeatureEnabled by defaultDescription
filterMenu*Filter100FiltertrueShows a submenu to control filtering. See Filter submenu.
toggleFilterBarHide filter bar / Show filter bar120FilterBarfalseToggles filter bar visibility
columnPickerColumns200ColumnPickertrueShows a submenu to control columns visibility
>column.id*column.text*ColumnPickertrueCheck item to hide/show corresponding column
hideColumnHide column210ColumnPickertrueHides selected column
sortAscSort ascending300SorttrueSorts records in the store by the column field in ascending order
sortDescSort descending310SorttrueSorts records in the store by the column field in descending order
multiSortMulti sort320SorttrueShows a submenu to control multi-sorting
>addSortAscAdd ascending sorting330SorttrueAdds additional ascending sorting by the column field
>addSortDescAdd descending sorting340SorttrueAdds additional ascending sorting by the column field
>removeSorterRemove sorter350SorttrueStops sorting by selected column field
groupAscGroup ascending400GrouptrueGroups and sorts records in the store by the column field in ascending order
groupDescGroup descending410GrouptrueGroups and sorts records in the store by the column field in descending order
groupRemoveStop grouping420GrouptrueStops grouping
*
items that are generated dynamically
>
first level of submenu

Removing default items

To remove a default item no matter if it is provided by a context menu feature, or it is provided by another feature, configure it as false in the items config of the context menu feature:

const grid = new Grid({
    features : {
        // This will enable Filter feature and all its menu items in both cell and header menus
        filter   : true,
        cellMenu : {
            items : {
                // Remove "Delete record" default item
                removeRow : false,
                // Remove "Before" and "After" items provided by Filter feature to only have "On" option for Date columns
                filterDateBefore : false, 
                filterDateAfter : false
            }
        },
        headerMenu : {
            items : {
                // Remove "Edit filter" item provided by Filter feature to only have "Remove filter" option in case a filter is applied to the column field
                filterEdit : false
            }
        }
    }
});

To remove a default subitem, configure the parent item menu and set corresponding items to false:

const grid = new Grid({
    features : {
        headerMenu : {
            items : {
                multiSort : {
                    menu : {
                        // Remove "Add descending sorting" item provided by Sort feature to only have ascending sorting
                        addSortDesc : false
                    }
                }
            }
        }
    }
});
Disable menu items
//<code-header>
fiddle.title = 'Disable menu items';
//</code-header>
const grid = new Grid({
    appendTo : targetElement,

    autoHeight : true,
    rowHeight  : 50,
    flex       : 1,

    columns : [
        { text : 'Name', field : 'name', width : 160 },
        { text : 'Start', field : 'startDate', width : 160 }
    ],

    data : [
        { id : 1, name : 'Mr Boss', startDate : '2020-08-17' }
    ],

    features : {
        // This will enable Filter feature and all its menu items in both cell and header menus
        filter   : { property : 'name', value : 'Boss' },
        cellMenu : {
            items : {
                // Remove "Delete record" default item
                removeRow        : false,
                // Remove "Before" and "After" items provided by Filter feature to only have "On" option for Date columns
                filterDateBefore : false,
                filterDateAfter  : false
            }
        },
        headerMenu : {
            items : {
                // Remove "Edit filter" item provided by Filter feature to only have "Remove filter" option in case a filter is applied to the column field
                filterEdit : false,
                multiSort  : {
                    menu : {
                        // Remove "Add descending sorting" item provided by Sort feature to only have ascending sorting
                        addSortDesc : false
                    }
                }
            }
        }
    }
});

Customize default items

The default items can be customized by supplying config objects for them in the items config of the menu feature. These config objects will be merged with their default configs. Similar to removing default items, it does not matter, if the item is provided by the menu feature or not.

The order of the default items is determined by the weight property. The higher the weight, the further down they are displayed. See the table above for the default weights.

For example, to rename grouping items and move them above sorting items:

const grid = new Grid({
    features : {
        headerMenu : {
            items : {
                // Rename and move grouping items to be between "Hide column" (210) and "Sort ascending" (300)
                groupAsc    : {
                    text   : 'Group Aa..Zz',
                    weight : 290
                },
                groupDesc   : {
                    text   : 'Group Zz..Aa',
                    weight : 291
                },
                groupRemove : {
                    text   : 'Ungroup',
                    weight : 292
                }
            }
        }
    }
});

Try it out in this demo:

Customize menu items
//<code-header>
fiddle.title = 'Customize menu items';
//</code-header>
const grid = new Grid({
    appendTo : targetElement,

    autoHeight : true,
    rowHeight  : 50,
    flex       : 1,

    columns : [
        { text : 'Name', field : 'name', width : 160 }
    ],

    data : [
        { id : 1, name : 'Mr Boss' }
    ],

    features : {
        headerMenu : {
            items : {
                // Rename and move grouping items to be between "Hide column" (210) and "Sort ascending" (300)
                groupAsc : {
                    text   : 'Group Aa..Zz',
                    weight : 290
                },
                groupDesc : {
                    text   : 'Group Zz..Aa',
                    weight : 291
                },
                groupRemove : {
                    text   : 'Ungroup',
                    weight : 292
                }
            }
        }
    }
});

Add custom items

Custom items are added in the same way as you customize the built-in ones, add new properties to the items config of the menu feature to add new items. The key you choose to use for your item will be used as its ref, through which it can be accessed later.

Here we add a custom item to the cell menu to rename a selected person to Mark:

const grid = new Grid({
    features : {
        cellMenu : {
            items : {
                // Custom reference to the new menu item
                renameUser : {
                    text   : 'Rename to Mark',
                    cls    : 'b-separator', // Add a visual line above the item
                    weight : 1, // Insert at the top
                    onItem : ({ item, record, column }) => {
                        record.firstName = 'Mark';
                    }
                }
            }
        }
    }
});

Try the custom cell item here:

Menu add items
//<code-header>
fiddle.title = 'Menu add items';
//</code-header>
const grid = new Grid({
    appendTo : targetElement,

    autoHeight : true,
    rowHeight  : 50,
    flex       : 1,

    columns : [
        { text : 'Name', field : 'name', width : 160 }
    ],

    data : [
        { id : 1, name : 'Mr Boss' }
    ],

    features : {
        cellMenu : {
            items : {
                // Custom reference to the new menu item
                renameUser : {
                    text   : 'Rename to Mark',
                    cls    : 'b-separator', // Add a visual line above the item
                    weight : 1, // Insert at the top
                    onItem : ({ item, record, column }) => {
                        record.name = 'Mark';
                    }
                }
            }
        }
    }
});

Dynamic items processing

If you need to control items visibility or text depending on a dynamic condition, for example user authentication, or user access rights, you can mutate items in processItems hook provided by the menu.

Here we disable "Delete record", "Columns", and "Hide column" items based on a condition:

let accessGranted = false;

const grid = new Grid({
    features : {
        cellMenu   : {
            // Process cell items before showing the menu
            processItems({ items, column, record }) {
                // Not possible to delete rows if there are no rights for it
                if (!accessGranted) {
                    items.removeRow = false;
                }
            }
        },
        headerMenu : {
            // Process header items before showing the menu
            processItems({ items, column }) {
                // Not possible to change columns visibility if there are no rights for it
                if (!accessGranted) {
                    items.columnPicker = false;
                    items.hideColumn = false;
                }
            }
        }
    }
});

See it in action in this demo:

Dynamic menu
//<code-header>
fiddle.title = 'Dynamic menu';
//</code-header>
let accessGranted = false;

const grid = new Grid({
    appendTo   : targetElement,
    autoHeight : true,
    rowHeight  : 50,
    flex       : 1,

    columns : [
        { text : 'Name', field : 'name', width : 160 }
    ],

    data : [
        { id : 1, name : 'Mr Boss' }
    ],

    features : {
        cellMenu : {
            // Process cell items before showing the menu
            processItems({ items, column, record }) {
                // Not possible to delete rows if there are no rights for it
                if (!accessGranted) {
                    items.removeRow = false;
                }
            }
        },
        headerMenu : {
            // Process header items before showing the menu
            processItems({ items, column }) {
                // Not possible to change columns visibility if there are no rights for it
                if (!accessGranted) {
                    items.columnPicker = false;
                    items.hideColumn   = false;
                }
            }
        }
    },

    tbar : [
        {
            text        : 'Limited rights',
            toggleable  : true,
            pressed     : !accessGranted,
            icon        : 'fa fa-square',
            pressedIcon : 'fa fa-check-square',
            onToggle({ pressed }) {
                accessGranted = !pressed;
            }
        }
    ]
});