html5 scheduler dynamic event loading

The JavaScript Scheduler can load events from the server dynamically as the user scrolls.

Notes

  • The Scheduler fires onScroll event after every scrollbar position change.

  • The delay before the Scroll event is fired can be configured using scrollDelayDynamic property.

JavaScript Scheduler

Handle the onScroll event to supply events for the viewport.

See also:

Example

<script>
  const dp = new DayPilot.Scheduler("dp", {
    dynamicLoading: true,
    onScroll: async args => {
    const query = new URLSearchParams({
      start: args.viewport.start.toString(), end: args.viewport.end.toString(),
      resources: args.viewport.resources.join(",")
    });
    try { const {data} = await DayPilot.Http.get("/api/events?" + query); args.events = data; }
    catch { args.clearEvents = false; args.events = []; args.control.message("Could not load events."); }
    finally { args.loaded(); }
  },
    // ...
  });
  dp.init();

</script>

Replacing Events and Overlapping Requests

Keep args.clearEvents at its default true and return all events for the requested viewport, plus any extra dates you want to preload. In Pro since version 2026.4.7072, a slow response cannot replace results from a newer request that has already completed. While the newer request is still pending, the older result can be displayed.

This behavior applies to onScroll and onScrollEnd, with finite and infinite timelines. After the Scheduler is disposed, loading callbacks no longer update it. Your application can cancel unneeded HTTP requests.

Use args.clearEvents = false only when you want to merge the returned events with the existing set. In that mode, your application must handle conflicts between overlapping requests.

JavaScript Tutorials

Live Demo

API: dynamicLoading, heightSpec, height.

The examples request events overlapping the viewport's dates and resource IDs. On failure, the handler retains existing events by setting args.clearEvents = false; args.loaded() in finally completes the loading cycle in either case.

The framework examples use DayPilot Pro. For installation, see the Angular, React or Vue Scheduler guide.

Angular

Place the asynchronous onScroll function in config. Its args.control reference displays loading errors on the originating Scheduler.

import {Component} from "@angular/core";
import {DayPilot, DayPilotModule} from "daypilot-pro-angular";

@Component({
  selector: "app-scheduler-example",
  standalone: true,
  imports: [DayPilotModule],
  template: `
    
    <daypilot-scheduler [config]="config"></daypilot-scheduler>
  `
})
export class SchedulerExampleComponent {
  config: DayPilot.SchedulerConfig = {
    startDate: "2026-11-01",
    days: 365,
    scale: "Day",
    timeHeaders: [{groupBy: "Month"}, {groupBy: "Day", format: "d"}],
    resources: [{id: "A", name: "Room A"}, {id: "B", name: "Room B"}],
    events: [],
    dynamicLoading: true,
    heightSpec: "Fixed",
    height: 300,
    onScroll: async args => {
      const query = new URLSearchParams({start: args.viewport.start.toString(), end: args.viewport.end.toString(), resources: args.viewport.resources.join(",")});
      try { const {data} = await DayPilot.Http.get("/api/events?" + query); args.events = data; }
      catch { args.clearEvents = false; args.events = []; args.control.message("Could not load reservations."); }
      finally { args.loaded(); }
    }
  };

}

Angular Tutorial

React

Supply onScroll as a function prop alongside dynamicLoading. The callback returns events through the DayPilot arguments object.

import React from "react";
import {DayPilot, DayPilotScheduler} from "daypilot-pro-react";

export default function SchedulerExample() {

  return <div>

    <DayPilotScheduler
      startDate={"2026-11-01"}
      days={365}
      scale={"Day"}
      timeHeaders={[{groupBy: "Month"}, {groupBy: "Day", format: "d"}]}
      resources={[{id: "A", name: "Room A"}, {id: "B", name: "Room B"}]}
      events={[]}
      dynamicLoading={true}
      heightSpec={"Fixed"}
      height={300}
      onScroll={async args => {
        const query = new URLSearchParams({start: args.viewport.start.toString(), end: args.viewport.end.toString(), resources: args.viewport.resources.join(",")});
        try { const {data} = await DayPilot.Http.get("/api/events?" + query); args.events = data; }
        catch { args.clearEvents = false; args.events = []; args.control.message("Could not load reservations."); }
        finally { args.loaded(); }
      }}
    />
  </div>;
}

Vue

Bind the function using :onScroll="onScroll". It is a DayPilot callback prop, with the loading result supplied through args.events.

<script setup>
import {DayPilot, DayPilotScheduler} from "daypilot-pro-vue";

const startDate = "2026-11-01";
const days = 365;
const scale = "Day";
const timeHeaders = [{groupBy: "Month"}, {groupBy: "Day", format: "d"}];
const resources = [{id: "A", name: "Room A"}, {id: "B", name: "Room B"}];
const events = [];
const dynamicLoading = true;
const heightSpec = "Fixed";
const height = 300;
const onScroll = async args => {
  const query = new URLSearchParams({start: args.viewport.start.toString(), end: args.viewport.end.toString(), resources: args.viewport.resources.join(",")});
  try { const {data} = await DayPilot.Http.get("/api/events?" + query); args.events = data; }
  catch { args.clearEvents = false; args.events = []; args.control.message("Could not load reservations."); }
  finally { args.loaded(); }
};

</script>

<template>
  <div>

    <DayPilotScheduler
      :startDate="startDate"
      :days="days"
      :scale="scale"
      :timeHeaders="timeHeaders"
      :resources="resources"
      :events="events"
      :dynamicLoading="dynamicLoading"
      :heightSpec="heightSpec"
      :height="height"
      :onScroll="onScroll"
    />
  </div>
</template>

Vue Tutorial

ASP.NET WebForms

By default, events for the full grid (defined by StartDate and Days) are loaded from the server. The scheduler may become slow when displaying a large number of events.

There is an option to load only the events for the visible range. Events will be loaded and rendered as the users scrolls.

1. Activate the dynamic event loading mode using DynamicLoading property"

DynamicLoading="true"

2. Handle Scroll event:

OnScroll="DayPilotScheduler1_Scroll"

protected void DayPilotScheduler1_Scroll(object sender, DayPilot.Web.Ui.Events.ScrollEventArgs e)
{
  setDataSourceAndBind();
  DayPilotScheduler1.Update();
}

Information about the visible range is stored in the ViewPort property:

  • ViewPort.Start - Start of the visible range (DateTime)

  • ViewPort.End - End of the visible range (DateTime)

  • ViewPort.Resources - List of IDs (Value property) of the visible resources (List<string>)

Tutorial

Demo

ASP.NET MVC

Events can be loaded dynamically (on demand) as the user scrolls.

Enable Dynamic Event Loading

DynamicEventLoading = true

Load the Events upon Request

New events are requested from the server using OnScroll event every time the scrollbar position is changed.

Details about the new viewport are available in ViewPort property.

  • ViewPort.Start

  • ViewPort.End

  • ViewPort.Resources

Example

View

@Html.DayPilotScheduler("dps_dynamic", new DayPilotSchedulerConfig {
  BackendUrl = ResolveUrl("~/Scheduler/Backend"),
  ...
  DynamicLoading = true,
})

Backend Controller

protected override void OnScroll(ScrollArgs e)
{
  DateTime start = ViewPort.Start;
  DateTime end = ViewPort.End;
  List<string> resources = ViewPort.Resources;

  Events = new DataManager().GetEvents(start, end, resources);
  Update(CallBackUpdateType.EventsOnly);
}

Demo

Availability

Availability of this feature in DayPilot editions:

ProductLitePro
DayPilot for JavaScript
DayPilot for ASP.NET WebForms
DayPilot for ASP.NET MVC
DayPilot for Java