Customizing the Event, Schedule, and TimeAxis header menus

Bryntum Scheduler ships with built-in context menus for the locked grid cells and column headers, for events, and for the schedule zone and its header. All the context menu features are customizable. The Scheduler is built upon the Grid, so customization of the Cell menu and the Header menu can be found in the Grid docs.

Customization of the Event menu, the Schedule menu, and the TimeAxisHeader menu are similar to the context menus in Grid. and you will find more details about it in this guide.

Right-click an event, the schedule zone behind the event which is called "TimeAxis", and the header of the TimeAxis in the demo below to see it in action:

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

    autoHeight : true,
    rowHeight  : 40,
    barMargin  : 4,

    startDate : new Date(2018, 4, 6),
    endDate   : new Date(2018, 4, 13),

    viewPreset : {
        base            : 'dayAndWeek',
        timeColumnWidth : 30
    },

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

    resources : [
        { id : 1, name : 'Bernard' },
        { id : 2, name : 'Bianca' }
    ],

    events : [
        { id : 1, resourceId : 1, name : 'Right click me, the area behind me, and the header of the timeaxis', startDate : '2018-05-07', endDate : '2018-05-12' }
    ]
});

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

[@youtube](https://youtube.com/embed/dEnpeZvC4Rc)

Turning the menus off entirely

The menus are supplied by corresponding features: EventMenu feature provides menu for events, ScheduleMenu feature provides menu for the schedule zone, TimeAxisHeaderMenu feature provides menu for the header of the schedule zone. These features are enabled by default. To turn a feature off, configure it with false:

const scheduler = new Scheduler({
    features : {
        // Turn the Event menu off completely, will not be created
        eventMenu : false,
        // Turn the Schedule menu off completely, will not be created
        scheduleMenu : false,
        // Turn the TimeAxis Header menu off completely, will not be created
        timeAxisHeaderMenu : false
    }
});

Enabling or disabling the menus

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

const scheduler = new Scheduler({
    features : {
        eventMenu : {
            // The Event menu is created, but starts disabled
            disabled : true
        },
        scheduleMenu : {
            // The Schedule menu is created, but starts disabled
            disabled : true
        },
        timeAxisHeaderMenu : {
            // The TimeAxis Header menu is created, but starts disabled
            disabled : true
        }
    }
});

// To enable
scheduler.features.eventMenu.disabled = false;
scheduler.features.scheduleMenu.disabled = false;
scheduler.features.timeAxisHeaderMenu.disabled = false;

// To disable again
scheduler.features.eventMenu.disabled = true;
scheduler.features.scheduleMenu.disabled = true;
scheduler.features.timeAxisHeaderMenu.disabled = true;

Try it in the demo below:

Disable menu feature
//<code-header>
fiddle.title = 'Disable menu feature';
//</code-header>
const scheduler = new Scheduler({
    appendTo   : targetElement,
    autoHeight : true,
    rowHeight  : 40,
    barMargin  : 4,
    flex       : 1,

    tbar : [
        {
            text        : 'Event menu',
            toggleable  : true,
            icon        : 'fa fa-square',
            pressedIcon : 'fa fa-check-square',
            onToggle({ pressed }) {
                scheduler.features.eventMenu.disabled = !pressed;
            }
        },
        {
            text        : 'Schedule menu',
            style       : 'margin-inline-start: 10px',
            toggleable  : true,
            icon        : 'fa fa-square',
            pressedIcon : 'fa fa-check-square',
            onToggle({ pressed }) {
                scheduler.features.scheduleMenu.disabled = !pressed;
            }
        },
        {
            text        : 'TimeAxis Header menu',
            style       : 'margin-inline-start: 10px',
            toggleable  : true,
            icon        : 'fa fa-square',
            pressedIcon : 'fa fa-check-square',
            onToggle({ pressed }) {
                scheduler.features.timeAxisHeaderMenu.disabled = !pressed;
            }
        }
    ],

    startDate : new Date(2018, 4, 6),
    endDate   : new Date(2018, 4, 13),

    viewPreset : {
        base            : 'dayAndWeek',
        timeColumnWidth : 30
    },

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

    resources : [
        { id : 1, name : 'Bernard' },
        { id : 2, name : 'Bianca' }
    ],

    events : [
        {
            id         : 1,
            resourceId : 1,
            name       : 'Right click me, the area behind me, and the header of the timeaxis',
            startDate  : '2018-05-07',
            endDate    : '2018-05-12'
        }
    ],

    features : {
        eventMenu : {
            disabled : true
        },
        scheduleMenu : {
            disabled : true
        },
        timeAxisHeaderMenu : {
            disabled : true
        }
    }
});

Customizing the menu items

The menu items in the Event menu, in the Schedule menu, and in the TimeAxis 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 event menu items

Here is the list of menu items provided by the EventMenu feature and populated by the other features:

ReferenceTextWeightFeatureDescription
editEventEdit event100EventEditEdit in the event editor. Hidden when read-only
copyEventCopy event110EventCopyPasteCopy event or assignment. Hidden when read-only
cutEvent Cut event120EventCopyPasteCut event or assignment. Hidden when read-only
deleteEventDelete event200EventMenuRemove event. Hidden when read-only
unassignEventUnassign event300EventMenuUnassign event. Hidden when read-only, shown for multi-assignment
splitEventSplit event650Scheduler Pro onlySplit an event into two segments at the mouse position
renameSegmentRename segment660Scheduler Pro onlyShow an inline editor to rename the segment
eventColorColor400EventMenuChoose background color for the event bar

Default scheduler zone menu items

The ScheduleMenu feature provides only one item:

ReferenceTextWeightFeatureDescription
addEventAdd event100ScheduleMenuAdd a new event for the hovered resource starting at the clicked point in time. Hidden if the Scheduler is read-only

Default timeaxis header menu items

Here is the list of menu items provided by the TimeAxisHeaderMenu feature and populated by the other features:

ReferenceTextWeightFeatureDescription
eventsFilterFilter tasks100EventFilterSubmenu for event filtering
>nameFilterBy name110EventFilterFilter by name
zoomLevelZoom200TimeAxisHeaderMenuSubmenu for timeline zooming
>zoomSlider-210TimeAxisHeaderMenuChanges current zoom level
dateRangeDate range300TimeAxisHeaderMenuSubmenu for timeline range
>startDateFieldStart date310TimeAxisHeaderMenuStart date for the timeline
>endDateFieldEnd date320TimeAxisHeaderMenuEnd date for the timeline
>leftShiftBtn<330TimeAxisHeaderMenuShift backward
>todayBtnToday340TimeAxisHeaderMenuGo to today
>rightShiftBtn>350TimeAxisHeaderMenuShift forward
currentTimeLineShow current timeline400TimeRangesShow current time line
>
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 scheduler = new Scheduler({
    features : {
        eventMenu : {
            items : {
                // Remove "Edit event" item provided by EventEdit feature
                editEvent : false
            }
        },
        scheduleMenu : {
            items : {
                // Remove "Add event" default item
                addEvent : false
            }
        },
        timeAxisHeaderMenu : {
            items : {
                // Remove "Filter tasks" item provided by EventFilter feature
                eventsFilter : false
            }
        }
    }
});

Removing subitems of the TimeAxis Header Menu is not supported.

Disable menu items
//<code-header>
fiddle.title = 'Disable menu items';
//</code-header>
const scheduler = new Scheduler({
    appendTo : targetElement,

    autoHeight : true,
    rowHeight  : 40,
    barMargin  : 4,

    startDate : new Date(2018, 4, 6),
    endDate   : new Date(2018, 4, 13),

    viewPreset : {
        base            : 'dayAndWeek',
        timeColumnWidth : 30
    },

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

    resources : [
        { id : 1, name : 'Bernard' },
        { id : 2, name : 'Bianca' }
    ],

    events : [
        { id : 1, resourceId : 1, name : 'Right click me, the area behind me, and the header of the timeaxis', startDate : '2018-05-07', endDate : '2018-05-12' }
    ],

    features : {
        eventMenu : {
            items : {
                // Remove "Edit event" item provided by EventEdit feature
                editEvent : false
            }
        },
        scheduleMenu : {
            items : {
                // Remove "Add event" default item
                addEvent : false
            }
        },
        timeAxisHeaderMenu : {
            items : {
                // Remove "Filter tasks" item provided by EventFilter feature
                eventsFilter : 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 the "Date range" item and move it above the "Zoom" item:

const scheduler = new Scheduler({
    features : {
        timeAxisHeaderMenu : {
            items : {
                // Rename and move "Date range" item to be above "Zoom" item (200)
                dateRange    : {
                    text   : 'Start/End',
                    weight : 190
                }
            }
        }
    }
});

Try it out in this demo:

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

    autoHeight : true,
    rowHeight  : 40,
    barMargin  : 4,

    startDate : new Date(2018, 4, 6),
    endDate   : new Date(2018, 4, 13),

    viewPreset : {
        base            : 'dayAndWeek',
        timeColumnWidth : 30
    },

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

    resources : [
        { id : 1, name : 'Bernard' },
        { id : 2, name : 'Bianca' }
    ],

    events : [
        { id : 1, resourceId : 1, name : 'Right click the header of the timeaxis', startDate : '2018-05-07', endDate : '2018-05-12' }
    ],

    features : {
        timeAxisHeaderMenu : {
            items : {
                // Rename and move "Date range" item to be above "Zoom" item (200)
                dateRange : {
                    text   : 'Start/End',
                    weight : 190
                }
            }
        }
    }
});

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 event menu to move the selected task 1 hour forward:

const scheduler = new Scheduler({
    features : {
        eventMenu : {
            items : {
                // Custom reference to the new menu item
                moveForward : {
                    text   : 'Move 1 hour ahead',
                    cls    : 'b-separator', // Add a visual line above the item
                    weight : 400, // Add the item to the bottom
                    onItem : ({ eventRecord }) => {
                        eventRecord.shift(1, 'hour');
                    }
                }
            }
        }
    }
});

Try new custom items here:

Add menu items
//<code-header>
fiddle.title = 'Add menu items';
//</code-header>
const scheduler = new Scheduler({
    appendTo : targetElement,

    autoHeight : true,
    rowHeight  : 40,
    barMargin  : 4,

    startDate : new Date(2018, 4, 6),
    endDate   : new Date(2018, 4, 13),

    viewPreset : {
        base            : 'dayAndWeek',
        timeColumnWidth : 30
    },

    columns : [{
        field      : 'name',
        text       : 'Name',
        width      : 100,
        htmlEncode : false,
        renderer   : ({ record, value }) => value + (record.star ? '<i class="fa fa-star"></i>' : '')
    }],

    resourceStore : {
        fields : [{ name : 'star', type : 'boolean', defaultValue : false }],
        data   : [
            { id : 1, name : 'Bernard' },
            { id : 2, name : 'Bianca' }
        ]
    },

    events : [
        { id : 1, resourceId : 1, name : 'Right click me', startDate : '2018-05-07', endDate : '2018-05-12' }
    ],

    features : {
        eventMenu : {
            items : {
                // Custom reference to the new menu item
                moveForward : {
                    text   : 'Move 1 hour ahead',
                    icon   : 'fa fa-long-arrow-alt-right',
                    cls    : 'b-separator', // Add a visual line above the item
                    weight : 400, // Add the item to the bottom
                    onItem : ({ eventRecord }) => {
                        eventRecord.shift(1, 'hour');
                    }
                }
            }
        },
        resourceTimeRanges : true,
        scheduleMenu       : {
            items : {
                // Custom reference to the new menu item
                timeBreak : {
                    text   : 'Add a day off',
                    icon   : 'fa fa-shield-virus',
                    cls    : 'b-separator', // Add a visual line above the item
                    weight : 200, // Add the item to the bottom
                    onItem : ({ date, resourceRecord }) => {
                        scheduler.resourceTimeRangeStore.add({
                            resourceId     : resourceRecord.id,
                            name           : 'Day off',
                            startDate      : new Date(date.getFullYear(), date.getMonth(), date.getDate()),
                            duration       : 1,
                            timeRangeColor : 'blue'
                        });
                    }
                }
            }
        },
        timeRanges         : true,
        timeAxisHeaderMenu : {
            items : {
                // Custom reference to the new menu item
                ventilationBreak : {
                    text   : 'Room ventilation',
                    icon   : 'fa fa-shield-virus',
                    cls    : 'b-separator', // Add a visual line above the item
                    weight : 500, // Add the item to the bottom
                    onItem : ({ event }) => {
                        const date = scheduler.getDateFromDomEvent(event);

                        scheduler.project.timeRangeStore.add({
                            startDate    : new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours()),
                            duration     : 2,
                            durationUnit : 'h'
                        });
                    }
                }
            }
        },
        cellMenu : {
            items : {
                // Custom reference to the new cell items
                star : {
                    text   : 'Give a star',
                    icon   : 'fa fa-star',
                    cls    : 'b-separator', // Add a visual line above the item
                    weight : 500, // Add the item to the bottom
                    onItem : ({ record }) => {
                        record.star = true;
                    }
                },
                removeStar : {
                    text   : 'Remove star',
                    icon   : 'fa fa-star-half-alt',
                    cls    : 'b-separator', // Add a visual line above the item
                    weight : 500, // Add the item to the bottom
                    onItem : ({ record }) => {
                        record.star = false;
                    }
                }
            },
            // Process cell items before showing the menu
            processItems({ items, record }) {
                // Hide either star or removeStar item
                if (record.star) {
                    items.star = false;
                }
                else {
                    items.removeStar = false;
                }
            }
        },
        headerMenu : {
            items : {
                // Custom reference to the new cell items
                star : {
                    text   : 'Add a new guy',
                    icon   : 'fa fa-plus',
                    weight : 10, // Add the item to the top
                    onItem : () => {
                        scheduler.resourceStore.add({
                            name : 'New employee'
                        });
                    }
                }
            }
        }
    }
});

Runtime control of menu item visibility

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

Here we disable "Edit event", "Delete event", "Unassign event", and "Add event" items based on a condition:

let accessGranted = false;

const scheduler = new Scheduler({
    features : {
        eventMenu   : {
            // Process event items before showing the menu
            processItems({ items }) {
                // Not possible to edit, delete, or change event assignments if there are no rights for it
                if (!accessGranted) {
                    items.editEvent = false;
                    items.deleteEvent = false;
                    items.unassignEvent = false;
                }
            }
        },
        scheduleMenu : {
            // Process schedule zone items before showing the menu
            processItems({ items }) {
                // Not possible to add new events if there are no rights for it
                if (!accessGranted) {
                    items.addEvent = false;
                }
            }
        }
    }
});

See it in action in this demo:

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

const scheduler = new Scheduler({
    appendTo   : targetElement,
    autoHeight : true,
    rowHeight  : 40,
    barMargin  : 4,
    flex       : 1,

    startDate : new Date(2018, 4, 6),
    endDate   : new Date(2018, 4, 13),

    viewPreset : {
        base            : 'dayAndWeek',
        timeColumnWidth : 30
    },

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

    resources : [
        { id : 1, name : 'Bernard' },
        { id : 2, name : 'Bianca' }
    ],

    events : [
        {
            id         : 1,
            resourceId : 1,
            name       : 'Right click me and the area behind me',
            startDate  : '2018-05-07',
            endDate    : '2018-05-12'
        }
    ],

    features : {
        eventMenu : {
            // Process event items before showing the menu
            processItems({ items, column, record }) {
                // Not possible to edit, delete, or change event assignments if there are no rights for it
                if (!accessGranted) {
                    items.editEvent     = false;
                    items.deleteEvent   = false;
                    items.unassignEvent = false;
                }
            }
        },
        scheduleMenu : {
            // Process schedule zone items before showing the menu
            processItems({ items }) {
                // Not possible to add new events if there are no rights for it
                if (!accessGranted) {
                    items.addEvent = false;
                }
            }
        }
    },

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