DevExtreme v23.2 is now available.

Explore our newest features/capabilities and share your thoughts with us.

Your search did not match any results.

Context Menu Integration

Documentation

This demo shows how to create a context menu for appointments and cells using the onAppointmentContextMenu and onCellContextMenu functions.

Backend API
$(() => { const appointmentClassName = '.dx-scheduler-appointment'; const cellClassName = '.dx-scheduler-date-table-cell'; $('#scheduler').dxScheduler({ timeZone: 'America/Los_Angeles', dataSource: data, views: ['day', 'month'], currentView: 'month', currentDate: new Date(2020, 10, 25), startDayHour: 9, recurrenceEditMode: 'series', onAppointmentContextMenu(e) { updateContextMenu( false, appointmentContextMenuItems, appointmentClassName, itemTemplate, onItemClick(e), ); }, onCellContextMenu(e) { updateContextMenu(false, cellContextMenuItems, cellClassName, 'item', onItemClick(e)); }, resources: [{ fieldExpr: 'roomId', dataSource: resourcesData, label: 'Room', }], height: 730, }); const contextMenuInstance = $('#context-menu').dxContextMenu({ width: 200, dataSource: [], disabled: true, target: appointmentClassName, }).dxContextMenu('instance'); const updateContextMenu = function (disable, dataSource, target, itemTemplate, onItemClick) { contextMenuInstance.option({ dataSource, target, itemTemplate, onItemClick, disabled: disable, }); }; const itemTemplate = function (itemData) { return getAppointmentMenuTemplate(itemData); }; const onItemClick = function (contextMenuEvent) { return function (e) { e.itemData.onItemClick(contextMenuEvent, e); }; }; const createAppointment = function (e) { e.component.showAppointmentPopup({ startDate: e.cellData.startDate, }, true); }; const createRecurringAppointment = function (e) { e.component.showAppointmentPopup({ startDate: e.cellData.startDate, recurrenceRule: 'FREQ=DAILY', }, true); }; const groupCell = function (e) { const scheduler = e.component; if (scheduler.option('groups')) { scheduler.option({ crossScrollingEnabled: false, groups: undefined }); } else { scheduler.option({ crossScrollingEnabled: true, groups: ['roomId'] }); } }; const showCurrentDate = function (e) { e.component.option('currentDate', new Date()); }; const showAppointment = function (e) { e.component.showAppointmentPopup(e.appointmentData); }; const deleteAppointment = function (e) { e.component.deleteAppointment(e.appointmentData); }; const repeatAppointmentWeekly = function (e) { const itemData = e.appointmentData; e.component.updateAppointment(itemData, $.extend(itemData, { startDate: e.targetedAppointmentData.startDate, recurrenceRule: 'FREQ=WEEKLY', })); }; const setResource = function (e, clickEvent) { const itemData = e.appointmentData; e.component.updateAppointment(itemData, $.extend(itemData, { roomId: [clickEvent.itemData.id], })); }; const cellContextMenuItems = [ { text: 'New Appointment', onItemClick: createAppointment }, { text: 'New Recurring Appointment', onItemClick: createRecurringAppointment }, { text: 'Group by Room/Ungroup', beginGroup: true, onItemClick: groupCell }, { text: 'Go to Today', onItemClick: showCurrentDate }, ]; let appointmentContextMenuItems = [ { text: 'Open', onItemClick: showAppointment }, { text: 'Delete', onItemClick: deleteAppointment }, { text: 'Repeat Weekly', beginGroup: true, onItemClick: repeatAppointmentWeekly }, { text: 'Set Room', beginGroup: true, disabled: true }, ]; $.each(resourcesData, (i, item) => { item.onItemClick = setResource; }); appointmentContextMenuItems = $.merge(appointmentContextMenuItems, resourcesData); const getAppointmentMenuTemplate = function (itemData) { const template = $('<div></div>'); if (itemData.color) { template.append(`<div class='item-badge' style='background-color:${itemData.color};'></div>`); } template.append(itemData.text); return template; }; });
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>DevExtreme Demo</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script>window.jQuery || document.write(decodeURIComponent('%3Cscript src="js/jquery.min.js"%3E%3C/script%3E'))</script> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/23.2.5/css/dx.light.css" /> <script src="js/dx.all.js"></script> <script src="data.js"></script> <script src="index.js"></script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="context-menu"></div> <div id="scheduler"></div> </div> </body> </html>
.dx-menu-item-content span { margin-right: 5px; } .dx-menu-item-has-submenu .dx-icon-spinright { position: absolute; top: 7px; right: 2px; } .item-badge { text-align: center; float: left; margin-right: 12px; color: white; width: 18px; height: 18px; font-size: 19.5px; border-radius: 18px; margin-top: 2px; }
const data = [ { text: 'Watercolor Landscape', roomId: [1], startDate: new Date('2020-11-01T17:30:00.000Z'), endDate: new Date('2020-11-01T19:00:00.000Z'), recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10', }, { text: 'Oil Painting for Beginners', roomId: [2], startDate: new Date('2020-11-01T17:30:00.000Z'), endDate: new Date('2020-11-01T19:00:00.000Z'), recurrenceRule: 'FREQ=WEEKLY;BYDAY=SU,WE;COUNT=10', }, { text: 'Testing', roomId: [3], startDate: new Date('2020-11-01T20:00:00.000Z'), endDate: new Date('2020-11-01T21:00:00.000Z'), recurrenceRule: 'FREQ=WEEKLY;BYDAY=SU;WKST=TU;INTERVAL=2;COUNT=2', }, { text: 'Meeting of Instructors', roomId: [4], startDate: new Date('2020-11-01T17:00:00.000Z'), endDate: new Date('2020-11-01T17:15:00.000Z'), recurrenceRule: 'FREQ=DAILY;BYDAY=TU;UNTIL=20201203', }, { text: 'Recruiting students', roomId: [5], startDate: new Date('2020-10-24T18:00:00.000Z'), endDate: new Date('2020-10-24T19:00:00.000Z'), recurrenceRule: 'FREQ=YEARLY;BYWEEKNO=50;WKST=SU', recurrenceException: '20201212T190000Z', }, { text: 'Final exams', roomId: [3], startDate: new Date('2020-10-24T20:00:00.000Z'), endDate: new Date('2020-10-24T21:35:00.000Z'), recurrenceRule: 'FREQ=YEARLY;BYWEEKNO=51;BYDAY=WE,TH', }, { text: 'Monthly Planning', roomId: [4], startDate: new Date('2020-11-24T22:30:00.000Z'), endDate: new Date('2020-11-24T23:45:00.000Z'), recurrenceRule: 'FREQ=MONTHLY;BYMONTHDAY=28;COUNT=1', }, { text: 'Open Day', roomId: [5], startDate: new Date('2020-11-01T17:30:00.000Z'), endDate: new Date('2020-11-01T21:00:00.000Z'), recurrenceRule: 'FREQ=YEARLY;BYYEARDAY=333', }, ]; const resourcesData = [ { text: 'Room 101', id: 1, color: '#bbd806', }, { text: 'Room 102', id: 2, color: '#f34c8a', }, { text: 'Room 103', id: 3, color: '#ae7fcc', }, { text: 'Meeting room', id: 4, color: '#ff8817', }, { text: 'Conference hall', id: 5, color: '#03bb92', }, ];