Notes

  • Resources are displayed on the vertical (Y) axis.

  • In Gantt and Timesheet (Days) modes the rows will be generated automatically. The Resources array will have no effect.

  • Each resource has an ID that is used for arranging events into the rows (it must match event.resource property).

  • Resources can be organized in a tree hierarchy.

JavaScript Scheduler

How to Initialize the Scheduler Rows

You can specify the resources using resources property during Scheduler initialization:

<div id="dp"></div>
<script type="text/javascript">

  var dp = new DayPilot.Scheduler("dp");
  // ...
  dp.resources = [
    { name: "Room A", id: "A" },
    { name: "Room B", id: "B" },
    { name: "Room C", id: "C" }
  ];
  dp.init();
</script>

How to Update the Scheduler Rows

You can also update the resources later by updating the resources array and calling update():

dp.resources = [
  { name: "Room A", id: "A" },
  { name: "Room B", id: "B" },
  { name: "Room C", id: "C" },
  { name: "Room D", id: "D" }
];
dp.update();

The update() method accepts a config object as a parameter. That lets you specify the properties to be updated:

const resources = [
  { name: "Room A", id: "A" },
  { name: "Room B", id: "B" },
  { name: "Room C", id: "C" },
  { name: "Room D", id: "D" }
];
dp.update({resources});

How to Load Row Data using a REST API Call

You can also use a helper method that loads the resources using an HTTP call and updates the Scheduler:

dp.rows.load("/api/resources");

The specified URL must return the resources in JSON format:

[
  { "name": "Room A", "id": "A" },
  { "name": "Room B", "id": "B" },
  { "name": "Room C", "id": "C" },
  { "name": "Room D", "id": "D" }
]

JavaScript Tutorials

API: update.

The examples start with no resources. Load rooms requests a JSON array containing resource id and name fields; tree nodes may also contain children. The response replaces the resource collection through update().

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

Angular

The asynchronous button method applies loaded resources through the control obtained using @ViewChild.

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

@Component({
  selector: "app-scheduler-example",
  standalone: true,
  imports: [DayPilotModule],
  template: `
    <button (click)="action0()">Load rooms</button>
    <daypilot-scheduler [config]="config" #scheduler></daypilot-scheduler>
  `
})
export class SchedulerExampleComponent {
  @ViewChild("scheduler") scheduler!: DayPilotSchedulerComponent;
  config: DayPilot.SchedulerConfig = {
    startDate: "2026-11-01",
    days: 30,
    scale: "Day",
    timeHeaders: [{groupBy: "Month"}, {groupBy: "Day", format: "d"}],
    resources: [],
    events: []
  };
  async action0() {
    const dp = this.scheduler.control;
    try { const {data} = await DayPilot.Http.get("/api/resources"); dp.update({resources: data}); }
    catch { await DayPilot.Modal.alert("Could not load rooms."); }
  }
}

Angular Tutorials

React

Retain the Scheduler API using controlRef so the button handler can apply the response after the request completes.

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

export default function SchedulerExample() {
  const scheduler = useRef(null);
  async function action0() {
    const dp = scheduler.current;
    try { const {data} = await DayPilot.Http.get("/api/resources"); dp.update({resources: data}); }
    catch { await DayPilot.Modal.alert("Could not load rooms."); }
  }
  return <div>
    <button onClick={action0}>Load rooms</button>
    <DayPilotScheduler
      controlRef={control => { scheduler.current = control; }}
      startDate={"2026-11-01"}
      days={30}
      scale={"Day"}
      timeHeaders={[{groupBy: "Month"}, {groupBy: "Day", format: "d"}]}
      resources={[]}
      events={[]}
    />
  </div>;
}

React Tutorials

Vue

The click function calls scheduler.value.control.update() through the Scheduler's template ref.

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

const scheduler = ref(null);
const startDate = "2026-11-01";
const days = 30;
const scale = "Day";
const timeHeaders = [{groupBy: "Month"}, {groupBy: "Day", format: "d"}];
const resources = [];
const events = [];
async function action0() {
  const dp = scheduler.value.control;
  try { const {data} = await DayPilot.Http.get("/api/resources"); dp.update({resources: data}); }
  catch { await DayPilot.Modal.alert("Could not load rooms."); }
}
</script>

<template>
  <div>
    <button @click="action0">Load rooms</button>
    <DayPilotScheduler ref="scheduler"
      :startDate="startDate"
      :days="days"
      :scale="scale"
      :timeHeaders="timeHeaders"
      :resources="resources"
      :events="events"
    />
  </div>
</template>

ASP.NET WebForms

Static configuration (.aspx)

<DayPilot:DayPilotScheduler 
  ID="DayPilotScheduler1" 
  runat="server" 
  TreeEnabled="true"
  ...
  >
  <Resources>
      <DayPilot:Resource Name="Locations" Value="GroupLocations" Expanded="True">
          <Children>
              <DayPilot:Resource Name="Room 1" Value="A" Expanded="False" />
              <DayPilot:Resource Name="Room 2" Value="B" Expanded="False" />
              <DayPilot:Resource Name="Room 3" Value="C" Expanded="False" />
              <DayPilot:Resource Name="Room 4" Value="D" Expanded="False" />
          </Children>
      </DayPilot:Resource>
      <DayPilot:Resource Name="People" Value="GroupPeople" Expanded="True">
          <Children>
          <DayPilot:Resource Name="Person 1" Value="E" Expanded="False" />
          <DayPilot:Resource Name="Person 2" Value="F" ToolTip="Test" Expanded="False" />
          <DayPilot:Resource Name="Person 3" Value="G" ToolTip="Test" Expanded="False" />
          <DayPilot:Resource Name="Person 4" Value="H" ToolTip="Test" Expanded="False" />
          </Children>
      </DayPilot:Resource>
      <DayPilot:Resource Name="Tools" Value="GroupTools" Expanded="True">
          <Children>
          <DayPilot:Resource Name="Tool 1" Value="I" Expanded="False" />
          <DayPilot:Resource Name="Tool 2" Value="J" ToolTip="Test" Expanded="False" />
          <DayPilot:Resource Name="Tool 3" Value="K" ToolTip="Test" Expanded="False" />
          <DayPilot:Resource Name="Tool 4" Value="L" ToolTip="Test" Expanded="False" />
          </Children>
      </DayPilot:Resource>
 </Resources>
</DayPilot:DayPilotScheduler>

Loading Resources from a Database

Resources only need to be set once (in Page_Load). 

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
    LoadResources();
  }
}

private void LoadResources()
{
  DataTable locations = new DataManager().GetLocations();
  DayPilotScheduler1.Resources.Clear();
  foreach (DataRow location in locations.Rows)
  {
    int id = Convert.ToInt32(location["LocationId"]);

    Resource r = new Resource((string)location["LocationName"], null); // using null for resources that can't be used
    r.IsParent = true; // marking as parent for the case that no children are loaded
    r.Expanded = true;
    DayPilotScheduler1.Resources.Add(r);

    DataTable rooms = new DataManager().GetLocations(id, Filter.Seats);
    
    foreach (DataRow dr in rooms.Rows)
    {
      Resource c = new Resource((string)dr["LocationName"], Convert.ToString(dr["LocationId"]));
      r.Children.Add(c);
    }
  }
}

The resources collection is persisted during subsequent PostBacks and CallBacks. This increases the size of the request/response but it is convenient and it keeps. 

This behavior can be turned off using SyncResourceTree property (SyncResourceTree="false"). In this case it is necessary to load the resources during every request:

protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
    // ...
  }

  LoadResources();
}

See also How to load the Scheduler resource tree from a database (SQL Server) (KB).

ASP.NET MVC

Resources only need to be set once (in OnInit). It is persisted during subsequent PostBacks and CallBacks.

protected override void OnInit(InitArgs e)
{
  LoadResources();

  UpdateWithMessage("Welcome!", CallBackUpdateType.Full);
}

private void LoadResources()
{
  foreach (DataRow r in new EventManager().GetResources().Rows)
  {
      Resources.Add((string) r["name"], Convert.ToString(r["id"]));
  }
}

Note that changing the resources requires full update:

UpdateWithMessage("Welcome!", CallBackUpdateType.Full);

The Scheduler resources (rows) can be created directly in the view or in the controller.

Creating Resources in the MVC View

@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig {
  BackendUrl = ResolveUrl("~/Scheduler/Backend"),
  Resources = new ResourceCollection {
      new Resource{Name = "Room A", Id = "A", Expanded = true, Children = new ResourceCollection
        {
            new Resource("Room A.1", "A.1"),
            new Resource("Room A.2", "A.2"),
            new Resource("Room A.3", "A.3")
        }},
      new Resource("Room B", "B"),
      new Resource("Room C", "C"),
      new Resource("Room D", "D")
  }
})

Creating Resources in the Backend Controller

The Resources collection should be filled in the OnInit() event handler. This event will be called immediately after the Scheduler is initialized on the client side. It is called only once.

The Resources collection will be persisted during all subsequent callback calls and it is not necessary to rebuild it on every callback.

public class SchedulerController : Controller
{
  //
  // GET: /Scheduler/

  public ActionResult Backend()
  {
      return new Dps().CallBack(this);
  }

  class Dps : DayPilotScheduler
  {
    protected override void OnInit(InitArgs e)
    {
      Resources.Add("Room A", "A");
      Resources.Add("Room B", "B");
      Resources.Add("Room C", "C");
      Resources.Add("Room D", "D");
      Resources.Add("Room E", "E");

      UpdateWithMessage("Welcome!", CallBackUpdateType.Full);
    }

    protected override void OnFinish()
    {
      if (UpdateType == CallBackUpdateType.None)
      {
          return;
      }

      Events = new EventManager().FilteredData(StartDate, StartDate.AddDays(Days)).AsEnumerable();

      DataIdField = "id";
      DataTextField = "name";
      DataStartField = "eventstart";
      DataEndField = "eventend";
      DataResourceField = "resource";
    }
  }
}

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