Overview

  • The Vue Scheduler component supports on-demand event loading. When enabled, the events will be loaded using a special event handler during scrolling.

  • On-demand loading dramatically improves performance for large data sets. It improves the initial loading time of the Vue Scheduler and limits the amount of data transferred between the browser and the server (at once).

  • To improve the user experience, you can preload events for areas adjacent to the current viewport.

  • For an introduction to using the Vue Scheduler component, please see Vue Scheduler: Build a Reservation Application in 5 Minutes.

  • The project includes a trial version of DayPilot Pro for JavaScript (see License below)

License

Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript. Buy a license.

How to Enable On-Demand Event Loading in the Vue Scheduler

vue scheduler on demand event loading viewport

By default, the Vue Scheduler events need to be loaded for the whole visible date rage (as defined using startDate and days properties).

config: {
  timeHeaders: [{"groupBy":"Month"},{"groupBy":"Day","format":"d"}],
  scale: "Day",
  days: 365,
  startDate: "2021-01-01",
  // ...
},

You can use the visibleStart() and visibleEnd() methods to get the start and end of the grid. In this case, visibleStart() will return "2021-01-01T00:00:00" and visibleEnd() will return "2022-01-01T00:00:00".

const start = this.scheduler.visibleStart();
const end = this.scheduler.visible.End();

const {data: events} = await DayPilot.Http.get(`/api/backend_events.php?from=${start}&to=${end}`);
this.scheduler.update({events});

To improve performance, the Vue Scheduler only renders events for the current viewport (see progressive rendering). The raw Scheduler performance is quite good but if you display large datasets it will take a long time to load the data from the server. This will have impact on the server load, network traffic and network response time.

In such cases, it helps to switch to the dynamic event loading mode which loads the events for the current viewport only. Whenever the viewport changes (during scrolling, during window resize) the Scheduler fires onScroll event which you can use to load the event data.

First, it’s necessary to enable the dynamic loading mode:

config: {
  dynamicLoading: true,
  // ...
},

When the on-demand loading mode is enabled, you need to handle the onScroll event handler. The Scheduler calls onScroll during the initial load and whenever the current viewport changes.

config: {
  // ...
  dynamicLoading: true,
  onScroll: async args => {
    const viewport = args.viewport;
    const from = viewport.start;
    const to = viewport.end;

    const {data: events} = await DayPilot.Http.get(`/api/backend_events.php?from=${from}&to=${to}`);
    args.events = events;
    args.loaded();
  },

},

You can see that the loading logic is similar: The event handler calls backend_events.php and asks for the event data. In this case, it uses the viewport start and end to limit the date range. In this example, the from value is "2021-01-01T00:00:00" and the to value is "2021-01-19T00:00:00" (the end of the last cell visible in the viewport).

How to Get the Viewport Rows

vue scheduler on demand event loading viewport rows

If you display a small number of resources of the vertical axis, it might be enough to limit the horizontal range like in the previous example.

However, if there are many rows with resources (the Vue Scheduler will handle hundreds of rows) you may want to limit the event data to the rows in the current viewport.

The updated onScroll handler looks like this:

config: {
  // ...
  dynamicLoading: true,
  onScroll: async args => {
    const viewport = args.viewport;
    const from = viewport.start;
    const to = viewport.end;
    const rstart = viewport.resources[0];
    const rend = viewport.resources[viewport.resources.length - 1];

    const {data: events} = await DayPilot.Http.get(`/api/backend_events_viewport.php?from=${from}&to=${to}&rstart=${rstart}&rend=${rend}`);
    args.events = events;
    args.loaded();
  },

},

You can see that the args.viewport property holds a list of resources that are visible in the current viewport. You can either send the full list of resources ID or - if the row order is known - you can just send the first and the last resource ID like in this example.

How to Preload Events for Adjacent Areas

In order to improve the user experience, we can add one more change. Instead of loading events only for the current viewport, we will use a buffer and load events for an extended viewport - one month more to the left and one month more to the right.

We will also turn off the progressive rendering which is turned on by default. Progressive rendering optimizes drawing of events that are already loaded to keep the DOM size small. This is a great performance improvement but it introduces a short delay before the events are rendered during scrolling.

In this case, we only load events for a limited area so we can afford to render them in advance. This will display events in the adjacent areas immediately and there will be no delay when the user scrolls less than one month.

config: {
  // ...
  dynamicLoading: true,
  dynamicEventRendering: "Disabled",
  onScroll: async args => {
    const viewport = args.viewport;
    const from = viewport.start.addMonths(-1);
    const to = viewport.end.addMonths(1);
    const rstart = viewport.resources[0];
    const rend = viewport.resources[viewport.resources.length - 1];

    const {data: events} = await DayPilot.Http.get(`/api/backend_events_viewport.php?from=${from}&to=${to}&rstart=${rstart}&rend=${rend}`);
    args.events = events;
    args.loaded();
  },

},

How to Run the Project

The zip file includes two projects:

  • vue-scheduler-on-demand is the Vue front-end project

  • vue-scheduler-on-demand-php is the PHP backend project

You can run the Vue project using NPM:

npm run serve

The Vue project uses a proxy service to forward the API requests to the backend PHP project running on port 8090 (see vue.config.js in the project root).

You also need to run the PHP project on port 8090 using the built-in webserver.

Linux

php -S 127.0.0.1:8090 -t /home/daypilot/tutorials/vue-scheduler-on-demand-php

Windows

php.exe -S 127.0.0.1:8090 -t C:\Users\daypilot\tutorials\vue-scheduler-on-demand-php

The PHP project uses SQLite database. The SQLite database file (daypilot.sqlite) will be automatically created in the api folder of the PHP project (vue-scheduler-on-demand-php) and initialized with the following schema:

CREATE TABLE event (
    id          INTEGER  PRIMARY KEY AUTOINCREMENT,
    name        TEXT,
    start       DATETIME,
    [end]       DATETIME,
    resource_id INTEGER
);

CREATE TABLE resource (
    id   INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT
);