
The JavaScript Scheduler can load events from the server dynamically as the user scrolls.
Notes
The Scheduler fires
onScrollevent after every scrollbar position change.The delay before the Scroll event is fired can be configured using
scrollDelayDynamicproperty.
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
HTML5 Scheduler with Dynamic Event Loading (PHP backend)
JavaScript Scheduler: Dynamic Event Loading (ASP.NET Core Backend)
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 = trueLoad 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:
| Product | Lite | Pro |
|---|---|---|
| DayPilot for JavaScript | ||
| DayPilot for ASP.NET WebForms | ||
| DayPilot for ASP.NET MVC | ||
| DayPilot for Java |
DayPilot