-
AI-powered Extensions
-
Data Grid
-
Tree List
-
Chat
-
HTML Editor
-
Form
-
-
Data Grids / Data Management
-
Data Grid
- Overview
-
Data Binding
-
Filtering
- Sorting
-
Editing
-
Grouping
-
Selection
- Focused Row
- Paging
-
Scrolling
-
Columns
- AI Assistant
-
Master-Detail
-
Data Summaries
-
Drag & Drop
-
Export to PDF
-
Export to Excel
- Appearance
-
Customization
- State Persistence
-
Adaptability
-
Keyboard Navigation
- Right-To-Left Support
-
Tree List
- Overview
-
Data Binding
-
Filtering
- Sorting
-
Editing
-
Selection
- Focused Row
- Paging
-
Columns
- Drag & Drop
- State Persistence
- Adaptability
-
Keyboard Navigation
-
Card View
-
Pivot Grid
- Overview
-
Data Binding
-
Field Management
-
Data Summaries
- Drill Down
- Filtering
-
Scrolling
-
Export to Excel
- Chart Integration
- Customization
- State Persistence
-
Filter Builder
-
-
Data Visualization
-
Charts
- Overview
-
Data Binding
-
Common Concepts
-
Axis
-
Aggregation
-
Tooltips
-
Selection
-
Customization
-
Zooming
-
Export
-
-
Area Charts
-
Bar Charts
- Bullet Charts
-
Doughnut Charts
-
Financial Charts
-
Funnel and Pyramid Charts
-
Line Charts
- Pareto Chart
-
Pie Charts
-
Point Charts
-
Polar and Radar Charts
-
Range Charts
- Sankey Chart
-
Sparkline Charts
-
Tree Map
-
Gauges
- Overview
-
Runtime update
-
Bar Gauge
-
Circular Gauge
-
Linear Gauge
-
Diagram
- Overview
-
Data Binding
-
Featured Shapes
-
Custom Shapes
-
Document Capabilities
-
User Interaction
- UI Customization
- Adaptability
-
-
Scheduling / Planning
-
Scheduler
- Overview
-
Data Binding
-
Views
-
Appointments
-
Timetable
- Editing
-
Grouping
- Virtual Scrolling
- Drag & Drop
-
Customization
- Adaptability
-
Gantt
- Overview
- Data Binding
-
Filtering
- Sorting
- Strip Lines
- Export to PDF
- Validation
-
Customization
-
-
Messaging
-
WYSIWYG Editor
-
Forms
-
Data Editors
- Overview
-
Common Concepts
-
Calendar
- Check Box
- Color Box
-
Date Box
-
Date Range Box
-
Number Box
- Radio Group
-
Range Selector
- Range Slider
- Slider
- Switch
- Text Area
- Text Box
-
Drop-Downs
- Autocomplete
-
Drop Down Box
-
Select Box
-
Tag Box
-
Lookup
-
Buttons
-
File Upload / File Management
-
File Manager
- Overview
-
File System Types
-
Customization
-
File Uploader
-
-
Popup and Notifications
-
Navigation
- Overview
- Accordion
-
Action Sheet
-
Context Menu
-
Menu
- Multi View
-
Drawer
-
Tab Panel
-
Tabs
-
Toolbar
-
Stepper
- Pagination
-
List
-
Tree View
- Right-to-Left Support
-
Layout
-
Tile View
- Splitter
-
Gallery
- Scroll View
- Box
- Responsive Box
-
-
Interactive Wrappers
-
Sortable
- Resizable
-
-
Progress Indicators
-
Maps
- Overview
-
Map
-
Vector Map
-
Data Binding
- Multiple Layers
-
Markers
- Legend
-
Zooming and Panning
-
Customization
-
-
Localization
Related Demos:
Your search did not match any results.
Vue Scheduler - Context Menu
This demo shows how to create a context menu for appointments and cells using the onAppointmentContextMenu and onCellContextMenu functions.
Backend API
<template>
<div>
<DxScheduler
time-zone="America/Los_Angeles"
:groups="groups"
:data-source="dataSource"
:views="views"
:current-date="currentDate"
:cross-scrolling-enabled="crossScrollingEnabled"
:start-day-hour="9"
:height="730"
:on-appointment-context-menu="onAppointmentContextMenu"
:on-cell-context-menu="onCellContextMenu"
current-view="month"
recurrence-edit-mode="series"
>
<DxResource
:data-source="resourcesData"
field-expr="roomId"
label="Room"
icon="conferenceroomoutline"
/>
</DxScheduler>
<DxContextMenu
:data-source="contextMenuItems"
:width="200"
target=".dx-scheduler"
:on-item-click="onContextMenuItemClick"
:on-hiding="onContextMenuHiding"
item-template="itemTemplateSlot"
>
<template #itemTemplateSlot="{ data: itemData }">
<ItemTemplate :item-data="itemData"/>
</template>
</DxContextMenu>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { DxScheduler, DxResource, type DxSchedulerTypes } from 'devextreme-vue/scheduler';
import { DxContextMenu, type DxContextMenuTypes } from 'devextreme-vue/context-menu';
import ItemTemplate from './ItemTemplate.vue';
import { resourcesData, data } from './data.ts';
import type { ContextMenuItem } from './types';
const views = ['day', 'month'];
const currentDate = ref(new Date(2020, 10, 25));
const dataSource = data;
const groups = ref<string[]>([]);
const crossScrollingEnabled = ref(false);
const contextMenuItems = ref<ContextMenuItem[]>([]);
const onAppointmentContextMenu = (e: DxSchedulerTypes.AppointmentContextMenuEvent) => {
const items = getAppointmentContextMenuItems(e);
contextMenuItems.value = items;
};
const onCellContextMenu = (e: DxSchedulerTypes.CellContextMenuEvent) => {
const items = getCellContextMenuItems(e);
contextMenuItems.value = items;
};
const onContextMenuItemClick = (e: DxContextMenuTypes.ItemClickEvent<ContextMenuItem>) => {
e.itemData?.onItemClick?.(e);
};
const onContextMenuHiding = () => {
contextMenuItems.value = [];
};
const getAppointmentContextMenuItems = (
e: DxSchedulerTypes.AppointmentContextMenuEvent,
): ContextMenuItem[] => {
const scheduler = e.component;
const { appointmentData: appointment, targetedAppointmentData: targetedAppointment } = e;
return [
{
text: 'Open',
onItemClick: () => { scheduler.showAppointmentPopup(appointment); },
},
{
text: 'Delete',
onItemClick: () => { scheduler.deleteAppointment(appointment); },
},
{
text: 'Repeat Weekly',
beginGroup: true,
onItemClick: () => {
scheduler.updateAppointment(appointment, {
...appointment,
startDate: targetedAppointment?.startDate,
recurrenceRule: 'FREQ=WEEKLY',
});
},
},
{
text: 'Set Room',
beginGroup: true,
disabled: true,
},
...resourcesData.map((item) => ({
...item,
onItemClick: (clickEvent: DxContextMenuTypes.ItemClickEvent<ContextMenuItem>) => {
scheduler.updateAppointment(appointment, {
...appointment,
roomId: [clickEvent.itemData?.id],
});
},
})),
];
};
const getCellContextMenuItems = (
e: DxSchedulerTypes.CellContextMenuEvent,
): ContextMenuItem[] => {
const scheduler = e.component;
return [
{
text: 'New Appointment',
onItemClick: () => {
scheduler.showAppointmentPopup({
startDate: e.cellData.startDateUTC,
}, true);
},
},
{
text: 'New Recurring Appointment',
onItemClick: () => {
scheduler.showAppointmentPopup({
startDate: e.cellData.startDateUTC,
recurrenceRule: 'FREQ=DAILY',
}, true);
},
},
{
text: 'Group by Room/Ungroup',
beginGroup: true,
onItemClick: () => {
if (groups.value.length) {
groups.value = [];
crossScrollingEnabled.value = false;
} else {
groups.value = ['roomId'];
crossScrollingEnabled.value = true;
}
},
},
{
text: 'Go to Today',
onItemClick: () => {
currentDate.value = new Date();
},
},
];
};
</script>
<template>
<div>
<div>
<div
v-if="itemData.color"
:style="styleObject"
class="item-badge"
/>
{{ itemData.text }}
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const props = withDefaults(defineProps<{
itemData?: any
}>(), {
itemData: () => {},
});
const styleObject = ref({ backgroundColor: props.itemData.color });
</script>
<style scoped>
.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;
}
</style>
export 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',
},
];
export const resourcesData = [
{
text: 'Room 101',
id: 1,
color: '#1564C0',
}, {
text: 'Room 102',
id: 2,
color: '#C2185B',
}, {
text: 'Room 103',
id: 3,
color: '#7B1FA2',
}, {
text: 'Meeting room',
id: 4,
color: '#DD2C00',
}, {
text: 'Conference hall',
id: 5,
color: '#2E7D32',
},
];
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
import type { DxContextMenuTypes } from 'devextreme-vue/context-menu';
interface ResourceItem {
text: string;
id: number;
color: string;
}
export type ContextMenuItem = DxContextMenuTypes.Item & Partial<ResourceItem> & {
onItemClick?: (e: DxContextMenuTypes.ItemClickEvent<ContextMenuItem>) => void
};
<!DOCTYPE html>
<html lang="en">
<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=5.0" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/26.1.5/css/dx.light.css" />
<link rel="stylesheet" type="text/css" href="./bundle.css" />
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"> </div>
</div>
<script src="bundles/vendor/vue.vendor.js"></script>
<script src="./bundle.js"></script>
</body>
</html>