DevExtreme v24.1 is now available.

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

Your search did not match any results.

Work Shifts

This demo uses the Scheduler component’s offset property to indicate the starting point of a day. The Scheduler’s offset can be set in multiples of 5 and can range from -1440 minutes (-24 hours) to 1440 minutes (24 hours).

For instance, if you set the offset to -120, like the First shift in this demo, the day begins at 10:00 PM on the previous day instead of 00:00. If you set the offset to 360, like the Second shift, the day begins at 6:00 AM.

You can also combine this property with startDayHour, endDayHour, and cellDuration to obtain desired display results.

Backend API
<template> <div class="options"> <div class="option"> <div class="label">Work Hours:</div> <div class="value"> <DxRadioGroup :items="shifts" :value="shifts[0]" layout="horizontal" :on-value-changed="onShiftChanged" /> </div> </div> </div> <br> <DxScheduler time-zone="America/Los_Angeles" :data-source="appointments" :current-date="currentDate" :views="views" current-view="workWeek" :start-day-hour="0" :end-day-hour="8" :offset="currentOffset" :cell-duration="60" :show-all-day-panel="false" /> </template> <script setup lang="ts"> import { ref } from 'vue'; import DxScheduler from 'devextreme-vue/scheduler'; import DxRadioGroup, { DxRadioGroupTypes } from 'devextreme-vue/radio-group'; import { appointments, shifts } from './data.ts'; const views = ['day', 'workWeek']; const currentDate = new Date(2021, 2, 30); const currentOffset = ref(shifts[0].offset); function onShiftChanged(e: DxRadioGroupTypes.ValueChangedEvent) { currentOffset.value = e.value.offset as number; } </script> <style scoped> .options { background-color: rgba(191, 191, 191, 0.15); margin-top: 20px; display: flex; align-items: flex-start; height: 100%; } .option { padding: 16px; display: flex; align-items: center; } .label, .value { display: inline-block; vertical-align: middle; } .label { width: 100px; } </style>
window.exports = window.exports || {}; window.config = { transpiler: 'plugin-babel', meta: { '*.vue': { loader: 'vue-loader', }, '*.ts': { loader: 'demo-ts-loader', }, '*.svg': { loader: 'svg-loader', }, 'devextreme/time_zone_utils.js': { 'esModule': true, }, 'devextreme/localization.js': { 'esModule': true, }, 'devextreme/viz/palette.js': { 'esModule': true, }, }, paths: { 'root:': '../../../../', 'npm:': '', }, map: { 'vue': 'npm:vue@3.2.47/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@24.1.4/cjs', 'devextreme-vue': 'npm:devextreme-vue@24.1.4/cjs', 'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js', 'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js', 'devexpress-diagram': 'npm:devexpress-diagram@2.2.10/dist/dx-diagram.js', 'devexpress-gantt': 'npm:devexpress-gantt@4.1.56/dist/dx-gantt.js', '@devextreme/runtime': 'npm:@devextreme/runtime@3.0.13', '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.8/standalone.js', 'prettier/parser-html': 'npm:prettier@2.8.8/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.13/inferno/package.json', ], babelOptions: { sourceMaps: false, stage0: true, }, }; System.config(window.config);
type Shift = { text: string; offset: number; }; type Appointment = { text: string, startDate: string, endDate: string, recurrenceRule?: string, }; export const shifts: Shift[] = [{ text: 'First shift', offset: -120, }, { text: 'Second shift', offset: 360, }, { text: 'Third shift', offset: 840, }]; export const appointments: Appointment[] = [{ text: 'Website Re-Design Plan', startDate: '2021-03-29T16:00:00.000Z', endDate: '2021-03-29T18:00:00.000Z', }, { text: 'Approve Personal Computer Upgrade Plan', startDate: '2021-03-31T01:30:00.000Z', endDate: '2021-03-31T03:00:00.000Z', }, { text: 'Final Budget Review', startDate: '2021-03-30T16:30:00.000Z', endDate: '2021-03-30T18:05:00.000Z', }, { text: 'New Brochures', startDate: '2021-04-01T23:30:00.000Z', endDate: '2021-04-02T02:30:00.000Z', }, { text: 'Approve New Online Marketing Strategy', startDate: '2021-03-31T16:30:00.000Z', endDate: '2021-03-31T18:30:00.000Z', }, { text: 'Prepare 2021 Marketing Plan', startDate: '2021-04-01T16:30:00.000Z', endDate: '2021-04-01T18:00:00.000Z', }, { text: 'Brochure Design Review', startDate: '2021-04-02T17:30:00.000Z', endDate: '2021-04-02T19:00:00.000Z', }, { text: 'Create Icons for Website', startDate: '2021-04-01T18:00:00.000Z', endDate: '2021-04-01T19:30:00.000Z', }, { text: 'Submit New Website Design', startDate: '2021-04-02T09:30:00.000Z', endDate: '2021-04-02T11:00:00.000Z', }, { text: 'Launch New Website', startDate: '2021-04-01T01:30:00.000Z', endDate: '2021-04-01T03:00:00.000Z', recurrenceRule: 'FREQ=WEEKLY;BYDAY=WE;INTERVAL=2', }, { text: 'Install New Router in Dev Room', startDate: '2021-03-29T08:00:00.000Z', endDate: '2021-03-29T09:00:00.000Z', }, { text: 'Upgrade Personal Computers', startDate: '2021-03-30T01:00:00.000Z', endDate: '2021-03-30T03:00:00.000Z', }, { text: 'Install New Database', startDate: '2021-03-31T08:30:00.000Z', endDate: '2021-03-31T10:00:00.000Z', }, { text: 'Update Customer Shipping Profiles', startDate: '2021-04-01T09:30:00.000Z', endDate: '2021-04-01T11:00:00.000Z', recurrenceRule: 'FREQ=WEEKLY;BYDAY=TH', }, { text: 'Upgrade Server Hardware', startDate: '2021-03-30T08:30:00.000Z', endDate: '2021-03-30T11:00:00.000Z', recurrenceRule: 'FREQ=MONTHLY;BYMONTHDAY=30', }];
import { createApp } from 'vue'; import App from './App.vue'; createApp(App).mount('#app');
<!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="" /> <script type="module"> import * as vueCompilerSFC from ""; window.vueCompilerSFC = vueCompilerSFC; </script> <script src=""></script> <script src=""></script> <script src=""></script> <script type="text/javascript" src="config.js"></script> <script type="text/javascript"> System.import("./index.ts"); </script> </head> <body class="dx-viewport"> <div class="demo-container"> <div id="app"></div> </div> </body> </html>