DayPilot Scheduler can load the resource tree children dynamically (upon clicking the expand [+] icon).

JavaScript
Set the dynamicChildren property of a resource to true for every resource that you want to load dynamically.
See also DayPilot.Scheduler.onLoadNode.
Scheduler config:
{
treeEnabled: true,
resources: [
{ name: "Building A", id: "A", dynamicChildren: true },
{ name: "Building B", id: "B", dynamicChildren: true },
{ name: "Building C", id: "C", dynamicChildren: true }
],
onLoadNode: (args) => {
args.async = true;
// simulate server-side load
setTimeout(() => {
const id = args.resource.id;
args.resource.children = [
{ name: "Room 111", id: `${id}111` },
{
name: "Room 112",
id: `${id}112`,
expanded: true,
children: [
{ name: "Room 112.a", id: `${id}112a` },
{ name: "Room 112.b", id: `${id}112b` }
]
},
{ name: "Room 113", id: `${id}113` }
];
args.loaded();
}, 100);
},
// ...
}Demo
API: treeEnabled, onLoadNode.
Expand Building A to request its child rooms as a JSON resource array. The handler sets args.async, assigns the returned children and calls args.loaded() on success. A failed request leaves the node available for another load attempt.
The framework examples use DayPilot Pro. For installation, see the Angular, React or Vue Scheduler guide.
Angular
Place onLoadNode in the typed config with treeEnabled and the initial parent resource.
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: 30,
scale: "Day",
timeHeaders: [{groupBy: "Month"}, {groupBy: "Day", format: "d"}],
resources: [{id: "building-a", name: "Building A", dynamicChildren: true}],
events: [],
treeEnabled: true,
onLoadNode: async args => {
args.async = true;
try {
const {data} = await DayPilot.Http.get("/api/resources/" + encodeURIComponent(String(args.resource.id)) + "/children");
args.resource.children = data;
args.loaded();
} catch { await DayPilot.Modal.alert("Could not load rooms. Click the expand icon to retry."); }
}
};
}
React
Supply the asynchronous loader as the onLoadNode prop. It returns children through the DayPilot node-loading arguments.
import React from "react";
import {DayPilot, DayPilotScheduler} from "daypilot-pro-react";
export default function SchedulerExample() {
return <div>
<DayPilotScheduler
startDate={"2026-11-01"}
days={30}
scale={"Day"}
timeHeaders={[{groupBy: "Month"}, {groupBy: "Day", format: "d"}]}
resources={[{id: "building-a", name: "Building A", dynamicChildren: true}]}
events={[]}
treeEnabled={true}
onLoadNode={async args => {
args.async = true;
try {
const {data} = await DayPilot.Http.get("/api/resources/" + encodeURIComponent(String(args.resource.id)) + "/children");
args.resource.children = data;
args.loaded();
} catch { await DayPilot.Modal.alert("Could not load rooms. Click the expand icon to retry."); }
}}
/>
</div>;
}
Vue
Bind the loader using :onLoadNode; it updates args.resource.children before completing the load.
<script setup>
import {DayPilot, DayPilotScheduler} from "daypilot-pro-vue";
const startDate = "2026-11-01";
const days = 30;
const scale = "Day";
const timeHeaders = [{groupBy: "Month"}, {groupBy: "Day", format: "d"}];
const resources = [{id: "building-a", name: "Building A", dynamicChildren: true}];
const events = [];
const treeEnabled = true;
const onLoadNode = async args => {
args.async = true;
try {
const {data} = await DayPilot.Http.get("/api/resources/" + encodeURIComponent(String(args.resource.id)) + "/children");
args.resource.children = data;
args.loaded();
} catch { await DayPilot.Modal.alert("Could not load rooms. Click the expand icon to retry."); }
};
</script>
<template>
<div>
<DayPilotScheduler
:startDate="startDate"
:days="days"
:scale="scale"
:timeHeaders="timeHeaders"
:resources="resources"
:events="events"
:treeEnabled="treeEnabled"
:onLoadNode="onLoadNode"
/>
</div>
</template>
ASP.NET WebForms
API
1. Specify Resource.ChildrenLoaded = false; for each tree node for which you would like to load the children on-demand.
private void preloadTree()
{
if (DayPilotScheduler1.Resources.Count == 0)
{
for(int i = 0; i < 5; i++)
{
Resource r = new Resource("A" + i, "A" + i);
r.ChildrenLoaded = false;
DayPilotScheduler1.Resources.Add(r);
}
}
}2. Each such node will have the [+] expand icon (TreeImageExpand property).
3. Clicking on this node icon will fire LoadNode event:
OnLoadNode="DayPilotScheduler1_LoadNode"4. In the event handler, add children to the selected resource (e.Resource). Remember to call full Update().
protected void DayPilotScheduler1_LoadNode(object sender, DayPilot.Web.Ui.Events.LoadNodeEventArgs e)
{
Resource r = e.Resource;
Resource child = new Resource("Test", Guid.NewGuid().ToString(), false);
r.Children.Add(child);
r.Expanded = true;
r.ChildrenLoaded = true;
DayPilotScheduler1.Update(CallBackUpdateType.Full);
}Demo
ASP.NET MVC
When displaying a resource tree, the resource children can be loaded on demand.
You have to mark the nodes with dynamic children using DynamicChildren property in OnBeforeResHeaderRender method:
@Html.DayPilotScheduler("dps_dynamictreeloading", new DayPilotSchedulerConfig {
BackendUrl = ResolveUrl("~/Scheduler/Backend"),
TreeEnabled = true,
Resources = new ResourceCollection {
new Resource{Name = "Room A", Id = "A", DynamicChildren = true},
new Resource{Name = "Room B", Id = "B", DynamicChildren = true},
new Resource{Name = "Room C", Id = "C", DynamicChildren = true},
new Resource{Name = "Room D", Id = "D", DynamicChildren = true},
new Resource{Name = "Room E", Id = "E", DynamicChildren = true},
}
})These nodes will be displayed with an expand [+] icon.

After clicking the expand icon, the server-side OnLoadNode method will be called:
protected override void OnLoadNode(LoadNodeArgs e)
{
Resource child = new Resource("Test", Guid.NewGuid().ToString());
child.DynamicChildren = true;
e.Resource.Children.Add(child);
e.Resource.Expanded = true;
Update(CallBackUpdateType.Full);
}
The node is then updated with the new icon and the DynamicChildren property is set to false.

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