v7.3.0
SupportExamplesFree Trial

Tutorial

Follow the steps in this tutorial to get this app up and running:

//<code-header> CSSHelper.insertRule('.result .b-sch-event { border-radius : 20px; }', targetElement.getRootNode()); //</code-header> const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Only used to allow scoping the custom CSS rule added above cls : 'result', // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15', // Event bar look and color eventStyle : 'traced', eventColor : 'indigo', // Configure Scheduler Pro features features : { // Configure the dependencies feature dependencies : { // Rounded line joints radius : 5, // Easier to click on lines clickWidth : 5 } }, // The view preset controls the time axis and its header viewPreset : { base : 'weekAndDayLetter', // Customize the header headers : [ // Week 16 ... on the top level { unit : 'week', dateFormat : 'Wp' }, // M, T, W ... on the bottom level { unit : 'day', dateFormat : 'd1' } ] }, // Columns in the grid part columns : [ { field : 'name', text : 'Name' }, { field : 'role', text : 'Role' } ], // The project handles data loading (and syncing, but not in this example) project : { loadUrl : 'data/SchedulerPro/examples/guides/tutorial/data.json', autoLoad : true, listeners : { // Listener for the `hasChanges` event, triggered when any store // handled by the project has changes hasChanges() { console.dir(scheduler.project.changes); // In a real app you would send the changes to the server here. // Then you would call `scheduler.project.acceptChanges()` to // clear local changes. } } }, // Declarative listener listeners : { eventClick({ eventRecord }) { Toast.show(`Clicked ${eventRecord.name}`); } } }); // Programmatic listener scheduler.on('beforeEventEdit', ({ eventRecord }) => { Toast.show(`Editing ${eventRecord.name}`); });

Project setup

To create an application, we will use Vitejs and choose vanilla JavaScript but you can use any other build tool of your choice.

To do so, execute:

npm create vite@latest my-schedulerpro-app -- --template vanilla

It will generate a vanilla JavaScript project.

Installing Dependencies

To install vite's dependencies:

cd my-schedulerpro-app
npm install

Next, add the bryntum dependencies. If you have the Bryntum SchedulerPro distribution, it provides pre-built JavaScript bundles. Copy the /build/schedulerpro.module.js, /build/schedulerpro.css & /build/svalbard-light.css files to the my-schedulerpro-app root folder.

After that, link the CSS in your index.html:

<head>
    <!-- Existing code -->

    <!-- Structural CSS -->
    <link rel="stylesheet" href="schedulerpro.css">
    <!-- Bryntum theme of your choice -->
    <link rel="stylesheet" href="svalbard-light.css" data-bryntum-theme>
</head>

Remove the counter.js from the root directory, we don't need it.

Minimal Scheduler Pro

Now we are going to add a minimal Scheduler Pro to the main.js file:

import { SchedulerPro } from './schedulerpro.module.js';

const scheduler = new SchedulerPro({
    // Where to render to, accepts an element or an element id
    appendTo : 'app',

    // Normally sizing would be handled by CSS, but for simplicity
    // we use fixed with and height for the tutorial 
    width  : 800,
    height : 600,

    // Dates that the time axis will span
    startDate : '2023-04-16',
    endDate   : '2023-05-15',
});

The page should now show something similar to this:

const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15' });

Running the app

Run the development server by executing:

npm run dev

The application is now available on http://localhost:5173.

Loading data

The scheduler above is very empty, lets populate it with some data. Scheduler Pro uses a project to hold all of its stores (eventStore, resourceStore, assignmentStore etc.). The project also contains a scheduling engine, used to schedule events based on constraints, dependencies, calendars etc. The engine is the main difference between Scheduler and Scheduler Pro.

Scheduler Pro accepts inline data, or it can use its project to load remote data using the CrudManager protocol. Depending on your setup you will want to pick one or the other.

If you for example have multiple widgets on your page displaying the same data, you might already have it available on the client - supplying it as inline data can then be cheaper than remotely loading it also for Scheduler Pro. But for most cases loading it remotely will be the best fit.

To load data remotely, configure project with a URL to load from. Modify the previous snippet, adding the following:

const scheduler = new SchedulerPro({

    // Code from the previous step omitted for brevity
    // ...

    // The project collects all data stores and handles loading 
    // (and syncing, but not in this example)
    project : {
        loadUrl  : 'data/data.json',
        autoLoad : true
    }
});

The response is expected in a specific format, see this guide. For more information on working with project data, see this guide.

The data used for this tutorial is available here: data.json. An excerpt from that file:

{
  "success" : true,
  "events" : {
    "rows" : [
      { 
        "id"         : 1, 
        "resourceId" : 1, 
        "startDate"  : "2023-04-17", 
        "duration"   : 7, 
        "name"       : "Project Kickoff"
      },
      {
        "..." : "..."
      }
    ]
  }
}

Note that although not shown above, the response also contains sections for resources, assignments and dependencies.

Make sure the url points to where you placed your data. With the correct load url now in place, you should be seeing the following:

const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15', // The project handles data loading (and syncing, but not in this example) project : { loadUrl : 'data/SchedulerPro/examples/guides/tutorial/data.json', autoLoad : true } });

Saving changes

As for loading data, you have multiple options for saving changes. You can use the project's crud manager functionality to sync changes automatically to the backend (by configuring it with a syncUrl and autoSync), which requires your backend to follow the CrudManager protocol. Or you can listen for changes and send them to your backend manually, trading ease of use on the client for flexibility on the server.

In this step we will use the latter approach. We will listen for changes, but since we have no backend in place we will just log the changes to the console. Modify the previous snippet, adding the following:

const scheduler = new SchedulerPro({
    // Code from the previous step omitted for brevity
    // ...

    project : {
        loadUrl  : 'data/data.json',
        autoLoad : true,
        // New code ↓
        listeners : {
            // Listener for the `hasChanges` event, triggered when any store
            // handled by the project has changes
            hasChanges() {
                console.dir(scheduler.project.changes);

                // In a real app you would send the changes to the server here.
                // Then you would call `scheduler.project.acceptChanges()` to 
                // clear local changes.
            }
        }
    }
});

Try it out here (be sure to open the console to see the output):

const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15', // The project handles data loading (and syncing, but not in this example) project : { loadUrl : 'data/SchedulerPro/examples/guides/tutorial/data.json', autoLoad : true, listeners : { // Listener for the `hasChanges` event, triggered when any store // handled by the project has changes hasChanges() { console.dir(scheduler.project.changes); // In a real app you would send the changes to the server here. // Then you would call `scheduler.project.acceptChanges()` to // clear local changes. } } } });

Adding columns

A Scheduler Pro by default consists of a left-hand side grid part with fixed width and a schedule part occupying the rest of the width. The grid part shows information about the resources. You can add an arbitrary number of columns to it (see the Scheduler columns guide for more info). In this step we add two columns:

const scheduler = new SchedulerPro({

    // Code from the previous steps omitted for brevity
    // ...

    // Columns in the grid part
    columns : [
        {
            field : 'name',
            text  : 'Name'
        }, {
            field : 'role',
            text  : 'Role'
        }
    ]
});

The app should now look something like this:

const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15', // Columns in the grid part columns : [ { field : 'name', text : 'Name' }, { field : 'role', text : 'Role' } ], // The project handles data loading (and syncing, but not in this example) project : { loadUrl : 'data/SchedulerPro/examples/guides/tutorial/data.json', autoLoad : true, listeners : { // Listener for the `hasChanges` event, triggered when any store // handled by the project has changes hasChanges() { console.dir(scheduler.project.changes); // In a real app you would send the changes to the server here. // Then you would call `scheduler.project.acceptChanges()` to // clear local changes. } } } });

Configuring features

Scheduler Pro ships with a large set of features that can be enabled/disabled and configured to affect the functionality of the component (see the Scheduler features guide for some of them). We are going to configure the Dependencies feature (which draws arrows between event bars to visualize dependencies between events).

Alter your Scheduler Pro config, add:

const scheduler = new SchedulerPro({

    // Code from the previous steps omitted for brevity
    // ...

    // Configure Scheduler Pro features
    features : {
        // Configure the dependencies feature
        dependencies : {
            // Rounded line joints
            radius     : 5,
            // Easier to click on lines
            clickWidth : 5
        }
    }
});

That change yields the following app:

const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15', // Configure Scheduler Pro features features : { // Configure the dependencies feature dependencies : { // Rounded line joints radius : 5, // Easier to click on lines clickWidth : 5 } }, // Columns in the grid part columns : [ { field : 'name', text : 'Name' }, { field : 'role', text : 'Role' } ], // The project handles data loading (and syncing, but not in this example) project : { loadUrl : 'data/SchedulerPro/examples/guides/tutorial/data.json', autoLoad : true, listeners : { // Listener for the `hasChanges` event, triggered when any store // handled by the project has changes hasChanges() { console.dir(scheduler.project.changes); // In a real app you would send the changes to the server here. // Then you would call `scheduler.project.acceptChanges()` to // clear local changes. } } } });

Reacting to events

Scheduler Pro, its features and data stores fire a number of events that you can listen to, for example Scheduler Pro fires eventClick when clicking an event, the resourceStore fires add when a new resources is added, etc. See the API docs for each class for all events (Scheduler Pro's events are for example listed here).

To catch an event, you can either specify declarative listeners in the config, or add them programmatically using the on method. In this step we will add a declarative listener for the eventClick event, and a programmatic listener for the beforeEventEdit event.

const scheduler = new SchedulerPro({
    // Code from the previous steps omitted for brevity
    // ...

    // Declarative listener
    listeners : {
        eventClick({ eventRecord }) {
            Toast.show(`Clicked ${eventRecord.name}`);
        }
    }
});

// Programmatic listener
scheduler.on('beforeEventEdit', ({ eventRecord }) => {
    Toast.show(`Editing ${eventRecord.name}`);
});
const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15', // Configure Scheduler Pro features features : { // Configure the dependencies feature dependencies : { // Rounded line joints radius : 5, // Easier to click on lines clickWidth : 5 } }, // Columns in the grid part columns : [ { field : 'name', text : 'Name' }, { field : 'role', text : 'Role' } ], // The project handles data loading (and syncing, but not in this example) project : { loadUrl : 'data/SchedulerPro/examples/guides/tutorial/data.json', autoLoad : true, listeners : { // Listener for the `hasChanges` event, triggered when any store // handled by the project has changes hasChanges() { console.dir(scheduler.project.changes); // In a real app you would send the changes to the server here. // Then you would call `scheduler.project.acceptChanges()` to // clear local changes. } } }, // Declarative listener listeners : { eventClick({ eventRecord }) { Toast.show(`Clicked ${eventRecord.name}`); } } }); // Programmatic listener scheduler.on('beforeEventEdit', ({ eventRecord }) => { Toast.show(`Editing ${eventRecord.name}`); });

Customizing the time axis

The cells in the schedule part are called "ticks". The size of these and the header above them can be customized using a view preset. Scheduler Pro ships with a number of presets, but you can also define your own or extend existing ones. See the API docs for PresetManager for the full listing.

For this tutorial, we are going to extend the existing weekAndDayLetter preset to modify the top header to show the week number instead of the first date of the week. Add the following to your app:

const scheduler = new SchedulerPro({

    // Code from the previous steps omitted for brevity
    // ...

    // The view preset controls the time axis and its header
    viewPreset : {
        base : 'weekAndDayLetter',

        // Customize the header
        headers : [
            // Week 16 ... on the top level
            {
                unit       : 'week',
                dateFormat : 'Wp'
            },
            // M, T, W ... on the bottom level
            {
                unit       : 'day',
                dateFormat : 'd1'
            }
        ]
    },
});

The header should now have changed in your app:

const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15', // Configure Scheduler Pro features features : { // Configure the dependencies feature dependencies : { // Rounded line joints radius : 5, // Easier to click on lines clickWidth : 5 } }, // The view preset controls the time axis and its header viewPreset : { base : 'weekAndDayLetter', // Customize the header headers : [ // Week 16 ... on the top level { unit : 'week', dateFormat : 'Wp' }, // M, T, W ... on the bottom level { unit : 'day', dateFormat : 'd1' } ] }, // Columns in the grid part columns : [ { field : 'name', text : 'Name' }, { field : 'role', text : 'Role' } ], // The project handles data loading (and syncing, but not in this example) project : { loadUrl : 'data/SchedulerPro/examples/guides/tutorial/data.json', autoLoad : true, listeners : { // Listener for the `hasChanges` event, triggered when any store // handled by the project has changes hasChanges() { console.dir(scheduler.project.changes); // In a real app you would send the changes to the server here. // Then you would call `scheduler.project.acceptChanges()` to // clear local changes. } } }, // Declarative listener listeners : { eventClick({ eventRecord }) { Toast.show(`Clicked ${eventRecord.name}`); } } }); // Programmatic listener scheduler.on('beforeEventEdit', ({ eventRecord }) => { Toast.show(`Editing ${eventRecord.name}`); });

Adding some style and color

For the last step of this tutorial we are going to apply some color and styling to the Scheduler Pro. For more info on the topic, see the Styling guide.

An events color is derived from three sources: the scheduler, the resource and the event itself. As you might have noticed already, one of the events have a different color than the others. This is determined by the eventColor field in its data. We are going to set an eventColor on the Scheduler Pro, to change all others.

An events look is determined in a similar way, by using the eventStyle field. In addition to changing the color, we are also going the change to another eventStyle for all events:

const scheduler = new SchedulerPro({

    // Code from the previous steps omitted for brevity
    // ...

    // Event bar look and color
    eventStyle : 'border',
    eventColor : 'indigo'
});

The green events are now indigo instead, and the style has changed:

const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15', // Event bar look and color eventStyle : 'traced', eventColor : 'indigo', // Configure Scheduler Pro features features : { // Configure the dependencies feature dependencies : { // Rounded line joints radius : 5, // Easier to click on lines clickWidth : 5 } }, // The view preset controls the time axis and its header viewPreset : { base : 'weekAndDayLetter', // Customize the header headers : [ // Week 16 ... on the top level { unit : 'week', dateFormat : 'Wp' }, // M, T, W ... on the bottom level { unit : 'day', dateFormat : 'd1' } ] }, // Columns in the grid part columns : [ { field : 'name', text : 'Name' }, { field : 'role', text : 'Role' } ], // The project handles data loading (and syncing, but not in this example) project : { loadUrl : 'data/SchedulerPro/examples/guides/tutorial/data.json', autoLoad : true, listeners : { // Listener for the `hasChanges` event, triggered when any store // handled by the project has changes hasChanges() { console.dir(scheduler.project.changes); // In a real app you would send the changes to the server here. // Then you would call `scheduler.project.acceptChanges()` to // clear local changes. } } }, // Declarative listener listeners : { eventClick({ eventRecord }) { Toast.show(`Clicked ${eventRecord.name}`); } } }); // Programmatic listener scheduler.on('beforeEventEdit', ({ eventRecord }) => { Toast.show(`Editing ${eventRecord.name}`); });

You can of course also use CSS to style the Scheduler Pro and its events. For example, to add more border-radius for a rounded look:

.b-sch-event { 
    border-radius : 20px; 
}

Much rounder now:

//<code-header> CSSHelper.insertRule('.result .b-sch-event { border-radius : 20px; }', targetElement.getRootNode()); //</code-header> const scheduler = new SchedulerPro({ // Where to render to, accepts an element or an element id appendTo : targetElement, // Only used to allow scoping the custom CSS rule added above cls : 'result', // Normally sizing would be handled by CSS, but for simplicity // we use fixed with and height for the tutorial // (commented out since docs browser handle sizing) // width : 800, height : 250, // Dates that the time axis will span startDate : '2023-04-16', endDate : '2023-05-15', // Event bar look and color eventStyle : 'traced', eventColor : 'indigo', // Configure Scheduler Pro features features : { // Configure the dependencies feature dependencies : { // Rounded line joints radius : 5, // Easier to click on lines clickWidth : 5 } }, // The view preset controls the time axis and its header viewPreset : { base : 'weekAndDayLetter', // Customize the header headers : [ // Week 16 ... on the top level { unit : 'week', dateFormat : 'Wp' }, // M, T, W ... on the bottom level { unit : 'day', dateFormat : 'd1' } ] }, // Columns in the grid part columns : [ { field : 'name', text : 'Name' }, { field : 'role', text : 'Role' } ], // The project handles data loading (and syncing, but not in this example) project : { loadUrl : 'data/SchedulerPro/examples/guides/tutorial/data.json', autoLoad : true, listeners : { // Listener for the `hasChanges` event, triggered when any store // handled by the project has changes hasChanges() { console.dir(scheduler.project.changes); // In a real app you would send the changes to the server here. // Then you would call `scheduler.project.acceptChanges()` to // clear local changes. } } }, // Declarative listener listeners : { eventClick({ eventRecord }) { Toast.show(`Clicked ${eventRecord.name}`); } } }); // Programmatic listener scheduler.on('beforeEventEdit', ({ eventRecord }) => { Toast.show(`Editing ${eventRecord.name}`); });

That's it, you finished the tutorial 👍 Happy coding!

Contents