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

html5 javascript scheduler dynamic tree node loading

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.

scheduler asp.net mvc dynamic tree loading

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.

scheduler asp.net mvc dynamic tree loading expanded

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