Overview
DevExtreme Vue Scheduler is a versatile scheduling component. Its main features include appointment editing, time zones support, vertical and horizontal orientation, and many more. You can use Vue syntax and techniques to instantiate and configure the Scheduler or handle its events. In addition, the component supports prop validation and templates that use named slots. Find out more about DevExtreme Vue components.
To get started with the DevExtreme Scheduler component, refer to the following tutorial for step-by-step instructions: Getting Started with Scheduler.
Feel free to share demo-related thoughts here.
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Thank you for the feedback!
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Backend API
<template>
<DxScheduler
time-zone="America/Los_Angeles"
:data-source="dataSource"
:current-date="currentDate"
:views="views"
:groups="groups"
:height="600"
:show-all-day-panel="true"
:first-day-of-week="1"
:start-day-hour="8"
:end-day-hour="18"
current-view="month"
data-cell-template="dataCellTemplate"
resource-cell-template="resourceCellTemplate"
>
<DxResource
:data-source="employees"
:allow-multiple="false"
label="Employee"
field-expr="employeeID"
/>
<template #resourceCellTemplate="{ data: employee }">
<ResourceCell
:employee="employee"
/>
</template>
<template #dataCellTemplate="{ data: cellData }">
<DataCell
:cell-data="cellData"
/>
</template>
</DxScheduler>
</template>
<script>
import { DxScheduler, DxResource } from 'devextreme-vue/scheduler';
import { employees, data } from './data.js';
import DataCell from './DataCell.vue';
import ResourceCell from './ResourceCell.vue';
export default {
components: {
DxScheduler,
DxResource,
DataCell,
ResourceCell,
},
data() {
return {
groups: ['employeeID'],
views: ['month'],
currentDate: new Date(2021, 5, 2, 11, 30),
employees,
dataSource: data,
};
},
};
</script>
<style>
.dx-scheduler-group-header,
.dx-scheduler-date-table-cell {
position: relative;
}
.dx-scheduler-date-table-other-month.dx-scheduler-date-table-cell {
opacity: 1;
color: rgba(0, 0, 0, 0.3);
}
.dx-scheduler-date-table-cell .dx-template-wrapper {
position: absolute;
width: 100%;
height: 100%;
padding-right: 6px;
}
</style>
<template>
<div
:class="markWeekEnd(cellData)"
>
<div :class="markTraining(cellData)">
{{ cellData.text }}
</div>
</div>
</template>
<script>
export default {
props: {
cellData: {
type: Object,
default: () => {},
},
},
methods: {
markWeekEnd(cellData) {
function isWeekEnd(date) {
const day = date.getDay();
return day === 0 || day === 6;
}
const classObject = {};
classObject[`employee-${cellData.groups.employeeID}`] = true;
classObject[`employee-weekend-${cellData.groups.employeeID}`] = isWeekEnd(cellData.startDate);
return classObject;
},
markTraining(cellData) {
const classObject = {
'day-cell': true,
};
classObject[
this.getCurrentTraining(cellData.startDate.getDate(), cellData.groups.employeeID)
] = true;
return classObject;
},
getCurrentTraining(date, employeeID) {
const result = (date + employeeID) % 3;
const currentTraining = `training-background-${result}`;
return currentTraining;
},
},
};
</script>
<style>
.day-cell {
height: 100%;
background-position: center center;
background-repeat: no-repeat;
}
.employee-1 {
background-color: rgba(86, 202, 133, 0.1);
}
.employee-2 {
background-color: rgba(255, 151, 71, 0.1);
}
.employee-weekend-1 {
background-color: rgba(86, 202, 133, 0.2);
}
.employee-weekend-2 {
background-color: rgba(255, 151, 71, 0.2);
}
.training-background-0 {
background-image: url("../../../../images/gym/icon-abs.png");
}
.training-background-1 {
background-image: url("../../../../images/gym/icon-step.png");
}
.training-background-2 {
background-image: url("../../../../images/gym/icon-fitball.png");
}
.dx-theme-material .name h2 {
font-size: 28px;
}
</style>
<template>
<div>
<div
:style="'background:' + employee.color"
class="name"
>
<h2>{{ employee.text }}</h2>
</div>
<div class="avatar">
<img :src="employee.data.avatar">
</div>
<div
:style="'color:' + employee.color"
class="info"
>
Age: {{ employee.data.age }}
<br>
<b>{{ employee.data.discipline }}</b>
</div>
</div>
</template>
<script>
export default {
props: {
employee: {
type: Object,
default: () => {},
},
},
};
</script>
<style>
.avatar {
width: 155px;
float: left;
overflow: hidden;
position: relative;
height: 125px;
}
.name {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
.name h2 {
color: #fff;
text-align: left;
padding: 0 0 5px 175px;
margin: 0;
}
.info {
width: auto;
text-align: left;
height: 100%;
font-size: 11pt;
font-weight: normal;
padding: 25px 20px;
color: #707070;
}
.dx-color-scheme-contrast .info {
color: #fff;
}
</style>
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#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/23.1.5/css/dx.light.css" />
<script src="https://unpkg.com/core-js@2.6.12/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>
export const employees = [{
text: 'John Heart',
id: 1,
color: '#56ca85',
avatar: '../../../../images/gym/coach-man.png',
age: 27,
discipline: 'ABS, Fitball, StepFit',
}, {
text: 'Sandra Johnson',
id: 2,
color: '#ff9747',
avatar: '../../../../images/gym/coach-woman.png',
age: 25,
discipline: 'ABS, Fitball, StepFit',
}];
export const data = [
{
text: 'Helen',
employeeID: 2,
startDate: new Date('2021-06-01T16:30:00.000Z'),
endDate: new Date('2021-06-01T18:30:00.000Z'),
}, {
text: 'Helen',
employeeID: 2,
startDate: new Date('2021-06-10T16:30:00.000Z'),
endDate: new Date('2021-06-11T18:30:00.000Z'),
}, {
text: 'Alex',
employeeID: 1,
startDate: new Date('2021-06-02T16:30:00.000Z'),
endDate: new Date('2021-06-02T18:30:00.000Z'),
}, {
text: 'Alex',
employeeID: 1,
startDate: new Date('2021-06-11T19:00:00.000Z'),
endDate: new Date('2021-06-11T20:00:00.000Z'),
}, {
text: 'Alex',
employeeID: 2,
startDate: new Date('2021-06-16T16:30:00.000Z'),
endDate: new Date('2021-06-16T18:30:00.000Z'),
}, {
text: 'Stan',
employeeID: 1,
startDate: new Date('2021-06-07T16:30:00.000Z'),
endDate: new Date('2021-06-07T18:30:00.000Z'),
}, {
text: 'Stan',
employeeID: 1,
startDate: new Date('2021-06-28T16:30:00.000Z'),
endDate: new Date('2021-06-28T18:30:00.000Z'),
}, {
text: 'Stan',
employeeID: 1,
startDate: new Date('2021-06-30T16:30:00.000Z'),
endDate: new Date('2021-06-30T18:30:00.000Z'),
}, {
text: 'Rachel',
employeeID: 2,
startDate: new Date('2021-06-04T16:30:00.000Z'),
endDate: new Date('2021-06-04T18:30:00.000Z'),
}, {
text: 'Rachel',
employeeID: 2,
startDate: new Date('2021-06-07T16:30:00.000Z'),
endDate: new Date('2021-06-07T18:30:00.000Z'),
}, {
text: 'Rachel',
employeeID: 1,
startDate: new Date('2021-06-21T16:30:00.000Z'),
endDate: new Date('2021-06-21T18:30:00.000Z'),
}, {
text: 'Kelly',
employeeID: 2,
startDate: new Date('2021-06-15T16:30:00.000Z'),
endDate: new Date('2021-06-15T18:30:00.000Z'),
}, {
text: 'Kelly',
employeeID: 2,
startDate: new Date('2021-06-29T16:30:00.000Z'),
endDate: new Date('2021-06-29T18:30:00.000Z'),
},
];
window.exports = window.exports || {};
window.config = {
transpiler: 'plugin-babel',
meta: {
'*.vue': {
loader: 'vue-loader',
},
'*.ts': {
loader: 'demo-ts-loader',
},
'*.svg': {
loader: 'svg-loader',
},
'devextreme/localization.js': {
'esModule': true,
},
},
paths: {
'root:': '../../../../../',
'npm:': 'https://unpkg.com/',
},
map: {
'vue': 'npm:vue@3.3.4/dist/vue.esm-browser.js',
'vue-loader': 'npm:dx-systemjs-vue-browser@1.1.1/index.js',
'demo-ts-loader': 'root:utils/demo-ts-loader.js',
'svg-loader': 'root:utils/svg-loader.js',
'mitt': 'npm:mitt/dist/mitt.umd.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@1.28.1/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign@1.1.0',
'devextreme': 'npm:devextreme@23.1.6/cjs',
'devextreme-vue': 'npm:devextreme-vue@23.1.6',
'jszip': 'npm:jszip@3.7.1/dist/jszip.min.js',
'devextreme-quill': 'npm:devextreme-quill@1.6.2/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.2/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.49/dist/dx-gantt.js',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate@7.4.11/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'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',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.4/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.4/parser-html.js',
},
packages: {
'devextreme-vue': {
main: 'index.js',
},
'devextreme': {
defaultExtension: 'js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.12/inferno/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
},
};
System.config(window.config);