JavaScript/jQuery Scheduler - Getting Started

jQuery
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.
Angular
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.
Vue
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.
React
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.

The Scheduler component emulates the user interface of Calendar applications on Windows or Mac OS.

This tutorial shows you the basics of Scheduler configuration. The preview below shows the expected result:

This article breaks the setup procedure into a series of configuration steps. We recommend that you follow the sequence, although you can skip some steps and revisit them later. You can also download the complete code from the following GitHub repository: getting-started-with-scheduler.

Create a Scheduler

jQuery

Add DevExtreme to your jQuery application and use the following code to create a Scheduler:

index.js
index.html
index.css
$(function() { 
    $("#scheduler").dxScheduler({
        // Configuration goes here
    });
});
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <link rel="stylesheet" type="text/css" href="https://unpkg.com/devextreme@24.2-next/dist/css/dx.light.css" />
        <link rel="stylesheet" href="index.css">

        <script src="https://unpkg.com/devextreme@24.2-next/dist/js/dx.all.js"></script>
        <script src="index.js"></script>
    </head>
    <body class="dx-viewport">
        <div id="scheduler"></div>
    </body>
</html>
#scheduler {
    height: 600px;
}
Angular

Add DevExtreme to your Angular application and use the following code to create a Scheduler:

app.component.html
app.component.ts
app.module.ts
app.component.css
<dx-scheduler id="scheduler">
    <!-- Configuration goes here -->
</dx-scheduler>
import { Component } from '@angular/core'; 

@Component({ 
    selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent { 

}
import { BrowserModule } from '@angular/platform-browser'; 
import { NgModule } from '@angular/core'; 
import { AppComponent } from './app.component'; 
import { DxSchedulerModule } from 'devextreme-angular'; 

@NgModule({ 
    declarations: [ 
        AppComponent 
    ], 
    imports: [ 
        BrowserModule, 
        DxSchedulerModule
    ], 
    providers: [ ], 
    bootstrap: [AppComponent] 
}) 
export class AppModule { }
#scheduler {
    height: 600px;
}
Vue

Add DevExtreme to your Vue application and use the following code to create a Scheduler:

App.vue
<template> 
    <DxScheduler id="scheduler>
        <!-- Configuration goes here -->
    </DxScheduler>
</template> 

<script>  
import 'devextreme/dist/css/dx.light.css'; 

import { DxScheduler } from 'devextreme-vue/scheduler'; 

export default { 
    components: {
        DxScheduler,
    }
} 
</script>

<style>
#scheduler {
    height: 600px;
}
</style>
React

Add DevExtreme to your React application and use the following code to create a Scheduler:

App.js
App.css
import 'devextreme/dist/css/dx.light.css';
import './App.css';

import { Scheduler } from 'devextreme-react/scheduler';

function App() {
    return (
        <Scheduler id="scheduler">
            {/* Configuration goes here */}
        </Scheduler>
    );
}

export default App;
#scheduler {
    height: 600px;
}

Bind the Scheduler to Data

The Scheduler can load and update data from these data source types:

Use the dataSource property to specify a data source. In this tutorial, we use a local array.

Once you assign the data source, you need to map field values to appointment attributes. If data objects include fields that match the predefined structure, the Scheduler recognizes them automatically and displays appointments without further configuration. To map other fields, use ...Expr properties. In this tutorial, the startDate and endDate fields are recognized automatically, whereas other field names are specified in the textExpr, allDayExpr, and recurrenceRuleExpr properties.

jQuery
index.js
data.js
index.html
$(function() { 
    $("#scheduler").dxScheduler({
        dataSource: appointments,
        textExpr: "title",
        allDayExpr: "dayLong",
        recurrenceRuleExpr: "recurrence"
    });
});
const appointments = [
    {
        title: "Install New Database",
        startDate: new Date("2021-05-23T08:45:00.000Z"),
        endDate: new Date("2021-05-23T09:45:00.000Z")
    }, {
        title: "Create New Online Marketing Strategy",
        startDate: new Date("2021-05-24T09:00:00.000Z"),
        endDate: new Date("2021-05-24T11:00:00.000Z")
    }, {
        title: "Upgrade Personal Computers",
        startDate: new Date("2021-05-25T10:15:00.000Z"),
        endDate: new Date("2021-05-25T13:30:00.000Z")
    }, {
        title: "Customer Workshop",
        startDate: new Date("2021-05-26T08:00:00.000Z"),
        endDate: new Date("2021-05-26T10:00:00.000Z"),
        dayLong: true,
        recurrence: "FREQ=WEEKLY;BYDAY=TU,FR;COUNT=10"
    }, {
        title: "Prepare Development Plan",
        startDate: new Date("2021-05-27T08:00:00.000Z"),
        endDate: new Date("2021-05-27T10:30:00.000Z")
    }, {
        title: "Testing",
        startDate: new Date("2021-05-23T09:00:00.000Z"),
        endDate: new Date("2021-05-23T10:00:00.000Z"),
        recurrence: "FREQ=WEEKLY;INTERVAL=2;COUNT=2"
    }, {
        title: "Meeting of Instructors",
        startDate: new Date("2021-05-24T10:00:00.000Z"),
        endDate: new Date("2021-05-24T11:15:00.000Z"),
        recurrence: "FREQ=DAILY;BYDAY=WE;UNTIL=20211001"
    }, {
        title: "Recruiting students",
        startDate: new Date("2021-05-25T08:00:00.000Z"),
        endDate: new Date("2021-05-25T09:00:00.000Z"),
        recurrence: "FREQ=YEARLY",
    }, {
        title: "Monthly Planning",
        startDate: new Date("2021-05-26T09:30:00.000Z"),
        endDate: new Date("2021-05-26T10:45:00.000Z"),
        recurrence: "FREQ=MONTHLY;BYMONTHDAY=28;COUNT=1"
    }, {
        title: "Open Day",
        startDate: new Date("2021-05-27T09:30:00.000Z"),
        endDate: new Date("2021-05-27T19:00:00.000Z"),
    }
];
<html>
    <head>
        <!-- ... -->
        <script src="data.js"></script>
    </head>
    <!-- ... -->
</html>
Angular
app.component.html
app.component.ts
app.service.ts
<dx-scheduler
    [dataSource]="appointments"
    textExpr="title"
    allDayExpr="dayLong"
    recurrenceRuleExpr="recurrence">
</dx-scheduler>
import { Component } from '@angular/core'; 
import { Appointment, AppService } from './app.service';

@Component({ 
    selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'],
    providers: [AppService]
}) 
export class AppComponent { 
    appointments: Appointment[];

    constructor(service: AppService) {
        this.appointments = service.getAppointments();
    }
}
import { Injectable } from '@angular/core';

export class Appointment {
    title: string;
    startDate: Date;
    endDate: Date;
    dayLong?: boolean;
    recurrence?: string;
}

const appointments: Appointment[] = [
    {
        title: "Install New Database",
        startDate: new Date("2021-05-23T08:45:00.000Z"),
        endDate: new Date("2021-05-23T09:45:00.000Z")
    }, {
        title: "Create New Online Marketing Strategy",
        startDate: new Date("2021-05-24T09:00:00.000Z"),
        endDate: new Date("2021-05-24T11:00:00.000Z")
    }, {
        title: "Upgrade Personal Computers",
        startDate: new Date("2021-05-25T10:15:00.000Z"),
        endDate: new Date("2021-05-25T13:30:00.000Z")
    }, {
        title: "Customer Workshop",
        startDate: new Date("2021-05-26T08:00:00.000Z"),
        endDate: new Date("2021-05-26T10:00:00.000Z"),
        dayLong: true,
        recurrence: "FREQ=WEEKLY;BYDAY=TU,FR;COUNT=10"
    }, {
        title: "Prepare Development Plan",
        startDate: new Date("2021-05-27T08:00:00.000Z"),
        endDate: new Date("2021-05-27T10:30:00.000Z")
    }, {
        title: "Testing",
        startDate: new Date("2021-05-23T09:00:00.000Z"),
        endDate: new Date("2021-05-23T10:00:00.000Z"),
        recurrence: "FREQ=WEEKLY;INTERVAL=2;COUNT=2"
    }, {
        title: "Meeting of Instructors",
        startDate: new Date("2021-05-24T10:00:00.000Z"),
        endDate: new Date("2021-05-24T11:15:00.000Z"),
        recurrence: "FREQ=DAILY;BYDAY=WE;UNTIL=20211001"
    }, {
        title: "Recruiting students",
        startDate: new Date("2021-05-25T08:00:00.000Z"),
        endDate: new Date("2021-05-25T09:00:00.000Z"),
        recurrence: "FREQ=YEARLY",
    }, {
        title: "Monthly Planning",
        startDate: new Date("2021-05-26T09:30:00.000Z"),
        endDate: new Date("2021-05-26T10:45:00.000Z"),
        recurrence: "FREQ=MONTHLY;BYMONTHDAY=28;COUNT=1"
    }, {
        title: "Open Day",
        startDate: new Date("2021-05-27T09:30:00.000Z"),
        endDate: new Date("2021-05-27T19:00:00.000Z"),
    }
];

@Injectable({
    providedIn: 'root'
})
export class AppService {
    getAppointments(): Appointment[] {
        return appointments;
    }
}
Vue
App.vue
data.js
<template> 
    <DxScheduler
        :data-source="appointments"
        text-expr="title"
        all-day-expr="dayLong"
        recurrence-rule-expr="recurrence">
    </DxScheduler>
</template> 

<script>
// ...
import { appointments } from './data.js';

export default {
    // ...
    data() {
        return {
            appointments: appointments
        };
    }
}
</script>
export const appointments = [
    {
        title: "Install New Database",
        startDate: new Date("2021-05-23T08:45:00.000Z"),
        endDate: new Date("2021-05-23T09:45:00.000Z")
    }, {
        title: "Create New Online Marketing Strategy",
        startDate: new Date("2021-05-24T09:00:00.000Z"),
        endDate: new Date("2021-05-24T11:00:00.000Z")
    }, {
        title: "Upgrade Personal Computers",
        startDate: new Date("2021-05-25T10:15:00.000Z"),
        endDate: new Date("2021-05-25T13:30:00.000Z")
    }, {
        title: "Customer Workshop",
        startDate: new Date("2021-05-26T08:00:00.000Z"),
        endDate: new Date("2021-05-26T10:00:00.000Z"),
        dayLong: true,
        recurrence: "FREQ=WEEKLY;BYDAY=TU,FR;COUNT=10"
    }, {
        title: "Prepare Development Plan",
        startDate: new Date("2021-05-27T08:00:00.000Z"),
        endDate: new Date("2021-05-27T10:30:00.000Z")
    }, {
        title: "Testing",
        startDate: new Date("2021-05-23T09:00:00.000Z"),
        endDate: new Date("2021-05-23T10:00:00.000Z"),
        recurrence: "FREQ=WEEKLY;INTERVAL=2;COUNT=2"
    }, {
        title: "Meeting of Instructors",
        startDate: new Date("2021-05-24T10:00:00.000Z"),
        endDate: new Date("2021-05-24T11:15:00.000Z"),
        recurrence: "FREQ=DAILY;BYDAY=WE;UNTIL=20211001"
    }, {
        title: "Recruiting students",
        startDate: new Date("2021-05-25T08:00:00.000Z"),
        endDate: new Date("2021-05-25T09:00:00.000Z"),
        recurrence: "FREQ=YEARLY",
    }, {
        title: "Monthly Planning",
        startDate: new Date("2021-05-26T09:30:00.000Z"),
        endDate: new Date("2021-05-26T10:45:00.000Z"),
        recurrence: "FREQ=MONTHLY;BYMONTHDAY=28;COUNT=1"
    }, {
        title: "Open Day",
        startDate: new Date("2021-05-27T09:30:00.000Z"),
        endDate: new Date("2021-05-27T19:00:00.000Z"),
    }
];
React
App.js
data.js
// ...
import { appointments } from './data.js';

function App() {
    return (
        <Scheduler
            dataSource={appointments}
            textExpr="title"
            allDayExpr="dayLong"
            recurrenceRuleExpr="recurrence">
        </Scheduler>
    );
}

export default App;
export const appointments = [
    {
        title: "Install New Database",
        startDate: new Date("2021-05-23T08:45:00.000Z"),
        endDate: new Date("2021-05-23T09:45:00.000Z")
    }, {
        title: "Create New Online Marketing Strategy",
        startDate: new Date("2021-05-24T09:00:00.000Z"),
        endDate: new Date("2021-05-24T11:00:00.000Z")
    }, {
        title: "Upgrade Personal Computers",
        startDate: new Date("2021-05-25T10:15:00.000Z"),
        endDate: new Date("2021-05-25T13:30:00.000Z")
    }, {
        title: "Customer Workshop",
        startDate: new Date("2021-05-26T08:00:00.000Z"),
        endDate: new Date("2021-05-26T10:00:00.000Z"),
        dayLong: true,
        recurrence: "FREQ=WEEKLY;BYDAY=TU,FR;COUNT=10"
    }, {
        title: "Prepare Development Plan",
        startDate: new Date("2021-05-27T08:00:00.000Z"),
        endDate: new Date("2021-05-27T10:30:00.000Z")
    }, {
        title: "Testing",
        startDate: new Date("2021-05-23T09:00:00.000Z"),
        endDate: new Date("2021-05-23T10:00:00.000Z"),
        recurrence: "FREQ=WEEKLY;INTERVAL=2;COUNT=2"
    }, {
        title: "Meeting of Instructors",
        startDate: new Date("2021-05-24T10:00:00.000Z"),
        endDate: new Date("2021-05-24T11:15:00.000Z"),
        recurrence: "FREQ=DAILY;BYDAY=WE;UNTIL=20211001"
    }, {
        title: "Recruiting students",
        startDate: new Date("2021-05-25T08:00:00.000Z"),
        endDate: new Date("2021-05-25T09:00:00.000Z"),
        recurrence: "FREQ=YEARLY",
    }, {
        title: "Monthly Planning",
        startDate: new Date("2021-05-26T09:30:00.000Z"),
        endDate: new Date("2021-05-26T10:45:00.000Z"),
        recurrence: "FREQ=MONTHLY;BYMONTHDAY=28;COUNT=1"
    }, {
        title: "Open Day",
        startDate: new Date("2021-05-27T09:30:00.000Z"),
        endDate: new Date("2021-05-27T19:00:00.000Z"),
    }
];

Run the code and ensure that the Scheduler properly displays all appointments.

Set the Current Date

To specify the current date, use the currentDate property:

jQuery
index.js
$(function() { 
    $("#scheduler").dxScheduler({
        //...
        currentDate: new Date(2021, 4, 25),
    });
});
Angular
app.component.html
app.component.ts
<dx-scheduler ...
    [(currentDate)]="currentDate">
</dx-scheduler>
import { Component } from '@angular/core'; 

@Component({ 
    selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent { 
    currentDate: Date = new Date(2021, 4, 25);
} 
Vue
App.vue
<template> 
    <DxScheduler ...
        :current-date.sync="currentDate">
    </DxScheduler>
</template>

<script> 
// ...
export default { 
    // ...
    data() {
        return {
            currentDate: new Date(2021, 4, 25),
        };
    }
} 
</script>
React
App.js
// ...
import { useCallback, useState } from 'react';

function App() {
    const [currentDate, setCurrentDate] = useState(new Date(2021, 4, 25));
    const handlePropertyChange = useCallback((e) => {
        if(e.name === 'currentDate') {
            setCurrentDate(e.value);
        }
    }, [])

    return (
        <Scheduler ...
            currentDate={currentDate}
            onOptionChanged={handlePropertyChange}>
        </Scheduler>
    );
}

export default App;

Configure Views

The Scheduler supports the following view types:

Use the views[] array to configure views. This array can contain strings (view types) and objects (view configurations). Use a string if the default view configuration suits you. Otherwise, declare an object that configures the view and specify the type and other properties within it. In the code below, the views[] array contains the Day, Week, and Month views. We specify the startDayHour and endDayHour properties for Day and Week; Month uses its default configuration.

To specify the view displayed initially, set the currentView property. In the following code, the initial view is Week.

jQuery
index.js
$(function() { 
    $("#scheduler").dxScheduler({ 
        // ...
        views: [{
            type: "day",
            startDayHour: 10,
            endDayHour: 22
        }, {
            type: "week",
            startDayHour: 10,
            endDayHour: 22
        },
        "month"
        ],
        currentView: "week"
    });
});
Angular
app.component.html
<dx-scheduler ...
    currentView="week">
    <dxi-view
        type="day"
        [startDayHour]="10"
        [endDayHour]="22">
    </dxi-view>
    <dxi-view
        type="week"
        [startDayHour]="10"
        [endDayHour]="22">
    </dxi-view>
    <dxi-view type="month"></dxi-view>
</dx-scheduler> 
Vue
App.vue
<template> 
    <DxScheduler ...
        current-view="week">
        <DxView
            type="day"
            :start-day-hour="10"
            :end-day-hour="22"
        />
        <DxView
            type="week"
            :start-day-hour="10"
            :end-day-hour="22"
        />
        <DxView type="month" />
    </DxScheduler>
</template> 

<script> 
// ...
import { DxScheduler, DxView } from 'devextreme-vue/scheduler';

export default { 
    components: {
        DxScheduler,
        DxView
    },
    // ...
} 
</script> 
React
App.js
// ...
import { Scheduler, View } from 'devextreme-react/scheduler';

function App() {
    return (
        <Scheduler ...
            defaultCurrentView="week">
            <View
                type="day"
                startDayHour={10}
                endDayHour={22}
            />
            <View
                type="week"
                startDayHour={10}
                endDayHour={22}
            />
            <View type="month" />
        </Scheduler>
    );
}

export default App;

Edit Appointments

Users can manage appointments in the following ways:

  • Add new appointments

  • Update appointments in an edit form

  • Resize an appointment to change its duration

  • Drag and drop an appointment to reschedule it

  • Remove appointments

Edit operations are enabled (the default setting). To disable an individual operation, set the corresponding property in the editing object to false. In this tutorial, we use the allowDragging property to disable appointment drag-and-drop.

jQuery
index.js
$(function() { 
    $("#scheduler").dxScheduler({ 
        // ...
        editing: {
            allowDragging: false
        },
    });
});
Angular
app.component.html
<dx-scheduler ... >
    <dxo-editing
        [allowDragging]="false">
    </dxo-editing>
</dx-scheduler> 
Vue
App.vue
<template> 
    <DxScheduler ... >
        <DxEditing
            :allow-dragging="false"
        />
    </DxScheduler>
</template> 

<script>
// ...
import {
    DxScheduler,
    // ...
    DxEditing
} from 'devextreme-vue/scheduler';

export default {
    components: {
        DxScheduler,
        // ...
        DxEditing
    },
    // ...
}
</script>
React
App.js
// ...
import {
    Scheduler,
    // ...
    Editing
} from 'devextreme-react/scheduler';

function App() {
    return (
        <Scheduler ... >
            <Editing
                allowDragging={false}
            />
        </Scheduler>
    );
}

export default App;

Time Zone Support

The Scheduler displays all appointments in the client time zone. To change this default behavior, specify a different time zone in the timeZone property. It accepts values from the IANA database. This tutorial sets the time zone to "Europe/Berlin".

Users can edit the time zones of individual appointments. To enable this functionality, set the editing.allowTimeZoneEditing property to true.

jQuery
index.js
$(function() { 
    $("#scheduler").dxScheduler({ 
        // ...
        editing: {
            // ...
            allowTimeZoneEditing: true
        },
        timeZone: "Europe/Berlin"
    });
});
Angular
app.component.html
<dx-scheduler ...
    timeZone="Europe/Berlin">
    <!-- ... -->
    <dxo-editing ...
        [allowTimeZoneEditing]="true">
    </dxo-editing>
</dx-scheduler> 
Vue
App.vue
<template> 
    <DxScheduler ...
        time-zone="Europe/Berlin">
        <!-- ... -->
        <DxEditing ...
            :allow-editing-time-zones="true"
        />
    </DxScheduler>
</template> 

<script> 
    // ...
</script> 
React
App.js
// ...
function App() {
    return (
        <Scheduler ...
            timeZone="Europe/Berlin">
            {/* ... */}
            <Editing ...
                allowTimeZoneEditing={true}
            />
        </Scheduler>
    );
}

export default App;

Enable Adaptive Mode

The Scheduler can adapt its interface to small screens. To enable this behavior, set the adaptivityEnabled property to true. See the following demo description for a full list of adaptability features: Adaptability.

jQuery
index.js
$(function() { 
    $("#scheduler").dxScheduler({
        // ...
        adaptivityEnabled: true
    });
});
Angular
app.component.html
<dx-scheduler ...
    [adaptivityEnabled]="true">
</dx-scheduler> 
Vue
App.vue
<template> 
    <DxScheduler ...
        :adaptivity-enabled="true">
    </DxScheduler>
</template>

<script> 
    // ...
</script> 
React
App.js
// ...
function App() {
    return (
        <Scheduler ...
            adaptivityEnabled={true}>
        </Scheduler>
    );
}

export default App;

For further information on the Scheduler component, refer to the following resources: