Your search did not match any results.
Scheduler

Context Menu Integration

Documentation

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

Copy to CodeSandBox
Apply
Reset
import React from 'react'; import Scheduler, { Resource } from 'devextreme-react/scheduler'; import ContextMenu from 'devextreme-react/context-menu'; import { data, resourcesData } from './data.js'; import { cellContextMenuItems, appointmentContextMenuItems, setResource } from './MenuItems.js'; import { AppointmentMenuTemplate } from './AppointmentTemplate.js'; const currentDate = new Date(2021, 2, 25); const views = ['day', 'month']; class App extends React.Component { constructor(props) { super(props); resourcesData.map(function(item) { item.onItemClick = setResource; }); this.appointmentContextMenuItems = appointmentContextMenuItems.concat(resourcesData); this.state = { contextMenuItems: [], target: null, disabled: true, contextMenuEvent: null }; this.onAppointmentContextMenu = this.onAppointmentContextMenu.bind(this); this.onContextMenuItemClick = this.onContextMenuItemClick.bind(this); this.onCellContextMenu = this.onCellContextMenu.bind(this); this.onContextMenuHiding = this.onContextMenuHiding.bind(this); } render() { const { contextMenuItems, target, disabled } = this.state; return ( <React.Fragment> <Scheduler dataSource={data} views={views} defaultCurrentView="month" defaultCurrentDate={currentDate} firstDayOfWeek={1} startDayHour={9} recurrenceEditMode="series" onAppointmentContextMenu={this.onAppointmentContextMenu} onCellContextMenu={this.onCellContextMenu} height={600} > <Resource dataSource={resourcesData} fieldExpr="roomId" label="Room" /> </Scheduler> <ContextMenu dataSource={contextMenuItems} width={200} target={target} disabled={disabled} onItemClick={this.onContextMenuItemClick} itemRender={AppointmentMenuTemplate} onHiding={this.onContextMenuHiding} /> </React.Fragment> ); } onAppointmentContextMenu(e) { this.setState({ target: '.dx-scheduler-appointment', disabled: false, contextMenuItems: this.appointmentContextMenuItems, contextMenuEvent: e }); } onContextMenuItemClick(e) { const { contextMenuEvent } = this.state; e.itemData.onItemClick(contextMenuEvent, e); } onCellContextMenu(e) { this.setState({ target: '.dx-scheduler-date-table-cell', disabled: false, contextMenuItems: cellContextMenuItems, contextMenuEvent: e }); } onContextMenuHiding() { this.setState({ disabled: true, contextMenuItems: [] }); } } export default App;
import React from 'react'; export function AppointmentMenuTemplate(itemData) { return (<div> {itemData.color ? <div className="item-badge" style={{ backgroundColor: itemData.color }} /> : ''} {itemData.text} </div>); }
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.js'; ReactDOM.render( <App />, document.getElementById('app') );
<!DOCTYPE html> <html> <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" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/20.2.3/css/dx.common.css" /> <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/20.2.3/css/dx.light.css" /> <script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script> <script src="https://unpkg.com/systemjs@0.21.3/dist/system.js"></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import('./index.js'); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"></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; }
export const data = [ { text: 'Watercolor Landscape', roomId: [1], startDate: new Date('2021-02-29T06:30:00.000Z'), endDate: new Date('2021-02-29T08:00:00.000Z'), recurrenceRule: 'FREQ=WEEKLY;BYDAY=TU,FR;COUNT=10' }, { text: 'Oil Painting for Beginners', roomId: [2], startDate: new Date('2021-02-29T06:30:00.000Z'), endDate: new Date('2021-02-29T08:00:00.000Z'), recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO,TH;COUNT=10' }, { text: 'Testing', roomId: [3], startDate: new Date('2021-02-29T09:00:00.000Z'), endDate: new Date('2021-02-29T10:00:00.000Z'), recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO;WKST=TU;INTERVAL=2;COUNT=2' }, { text: 'Meeting of Instructors', roomId: [4], startDate: new Date('2021-02-29T06:00:00.000Z'), endDate: new Date('2021-02-29T06:15:00.000Z'), recurrenceRule: 'FREQ=DAILY;BYDAY=WE;UNTIL=20210401' }, { text: 'Recruiting students', roomId: [5], startDate: new Date('2021-02-24T07:00:00.000Z'), endDate: new Date('2021-02-24T08:00:00.000Z'), recurrenceRule: 'FREQ=YEARLY;BYWEEKNO=14', recurrenceException: '20210411T100000' }, { text: 'Final exams', roomId: [3], startDate: new Date('2021-02-24T09:00:00.000Z'), endDate: new Date('2021-02-24T10:35:00.000Z'), recurrenceRule: 'FREQ=YEARLY;BYWEEKNO=24;BYDAY=TH,FR' }, { text: 'Monthly Planning', roomId: [4], startDate: new Date('2021-03-24T11:30:00.000Z'), endDate: new Date('2021-03-24T12:45:00.000Z'), recurrenceRule: 'FREQ=MONTHLY;BYMONTHDAY=27;COUNT=1' }, { text: 'Open Day', roomId: [5], startDate: new Date('2021-02-29T06:30:00.000Z'), endDate: new Date('2021-02-29T10:00:00.000Z'), recurrenceRule: 'FREQ=YEARLY;BYYEARDAY=87' } ]; export 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' } ];
System.config({ transpiler: 'plugin-babel', meta: { }, paths: { 'npm:': 'https://unpkg.com/' }, defaultExtension: 'js', map: { 'react': 'npm:react@16.14.0/umd/react.development.js', 'react-dom': 'npm:react-dom@16.14.0/umd/react-dom.development.js', 'prop-types': 'npm:prop-types@15.7.2/prop-types.js', 'rrule': 'npm:rrule@2.6.6/dist/es5/rrule.js', 'luxon': 'npm:luxon@1.25.0/build/global/luxon.min.js', 'es6-object-assign': 'npm:es6-object-assign@1.1.0', 'devextreme': 'npm:devextreme@20.2.3', 'devextreme-react': 'npm:devextreme-react@20.2.3', 'jszip': 'npm:jszip@3.5.0/dist/jszip.min.js', 'devextreme-quill': 'npm:devextreme-quill@0.9.5/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.0.0/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@2.0.0/dist/dx-gantt.js', 'preact': 'npm:preact@10.5.5/dist/preact.js', 'preact/hooks': 'npm:preact@10.5.5/hooks/dist/hooks.js', // SystemJS plugins 'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js', 'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js' }, packages: { 'devextreme': { defaultExtension: 'js' }, 'devextreme-react': { main: 'index.js' }, 'devextreme/events/utils': { main: 'index' }, 'devextreme/events': { main: 'index' }, 'es6-object-assign': { main: './index.js', defaultExtension: 'js' } }, babelOptions: { sourceMaps: false, stage0: true, react: true } });