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
Angular Scheduler
You can update the resources of the Angular Scheduler component using the following methods:
-
Automatic change detection (
config
attribute) -
Direct API
The automatic change detection of the object specified using config
attribute is convenient but the performance degrades if you use it with a large config object. If you display many resource in the Angular Scheduler, the config
object can grow very quickly. See also Angular Scheduler Performance topic.
1. Automatic change detection. You can load resource by modifying the resources
property of the config
object:
import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {DayPilot, DayPilotSchedulerComponent} from 'daypilot-pro-angular';
import {DataService} from './data.service';
@Component({
selector: 'scheduler-component',
template: `
<daypilot-scheduler [config]="config" #scheduler></daypilot-scheduler>`,
styles: [``]
})
export class SchedulerComponent implements AfterViewInit {
@ViewChild('scheduler')
scheduler!: DayPilotSchedulerComponent;
events: DayPilot.EventData[] = [];
config: DayPilot.SchedulerConfig = {
days: DayPilot.Date.today().daysInMonth(),
startDate: DayPilot.Date.today().firstDayOfMonth(),
};
constructor(private ds: DataService) {
}
ngAfterViewInit(): void {
this.ds.getResources().subscribe((result: DayPilot.ResourceData[]) => this.config.resources = result);
}
}
2. Use the direct API. This way the resources will be loaded directly to the Angular Scheduler and bypass the change detection.
import {AfterViewInit, Component, ViewChild} from '@angular/core';
import {DayPilot, DayPilotSchedulerComponent} from 'daypilot-pro-angular';
import {DataService} from './data.service';
@Component({
selector: 'scheduler-component',
template: `
<daypilot-scheduler [config]="config" #scheduler></daypilot-scheduler>`,
styles: [``]
})
export class SchedulerComponent implements AfterViewInit {
@ViewChild('scheduler')
scheduler!: DayPilotSchedulerComponent;
events: DayPilot.EventData[] = [];
config: DayPilot.SchedulerConfig = {
days: DayPilot.Date.today().daysInMonth(),
startDate: DayPilot.Date.today().firstDayOfMonth(),
};
constructor(private ds: DataService) {
}
ngAfterViewInit(): void {
this.ds.getResources().subscribe((resources: DayPilot.ResourceData[]) => this.scheduler.control.update({resources}));
}
}
Angular Tutorials
React Scheduler
There are two ways to load resource in the React Scheduler component. In React, both methods (automatic state detection and direct API call) have the same performance.
1. Use the resources
attribute of <DayPilotScheduler> tag. In this example, the React Scheduler loads all properties from the this.state
object as attributes. In order to load resources, simply update the resources
property of the this.state
object.
import React, {Component} from 'react';
import {DayPilot, DayPilotScheduler} from "daypilot-pro-react";
class Scheduler extends Component {
constructor(props) {
super(props);
this.state = {
timeHeaders: [{groupBy:"Month"},{groupBy:"Day",format:"d"}],
scale: "Day",
days: DayPilot.Date.today().daysInMonth(),
startDate: DayPilot.Date.today().firstDayOfMonth(),
treeEnabled: true,
// ...
};
}
componentDidMount() {
const resources = [
{name: "Group A", id: "GroupA", expanded: true, children: [
{name: "Resource A", id: "A"},
{name: "Resource B", id: "B"},
{name: "Resource C", id: "C"},
{name: "Resource D", id: "D"},
{name: "Resource E", id: "E"},
{name: "Resource F", id: "F"},
{name: "Resource G", id: "G"}
]
},
{name: "Group B", id: "GroupB", expanded: true, children: [
{name: "Resource H", id: "H"},
{name: "Resource I", id: "I"},
]}
];
this.setState({resources});
}
render() {
var {...config} = this.state;
return (
<div>
<DayPilotScheduler
{...config}
ref={component => {
this.scheduler = component && component.control;
}}
/>
</div>
);
}
}
export default Scheduler;
2. Use the direct API. You can update the resources by calling the update() method. All properties of the object passed as the parameter will be applied to the React Scheduler component.
import React, {Component} from 'react';
import {DayPilot, DayPilotScheduler} from "daypilot-pro-react";
class Scheduler extends Component {
constructor(props) {
super(props);
this.state = {
timeHeaders: [{groupBy:"Month"},{groupBy:"Day",format:"d"}],
scale: "Day",
days: DayPilot.Date.today().daysInMonth(),
startDate: DayPilot.Date.today().firstDayOfMonth(),
treeEnabled: true,
// ...
};
}
componentDidMount() {
const resources = [
{name: "Group A", id: "GroupA", expanded: true, children: [
{name: "Resource A", id: "A"},
{name: "Resource B", id: "B"},
{name: "Resource C", id: "C"},
{name: "Resource D", id: "D"},
{name: "Resource E", id: "E"},
{name: "Resource F", id: "F"},
{name: "Resource G", id: "G"}
]
},
{name: "Group B", id: "GroupB", expanded: true, children: [
{name: "Resource H", id: "H"},
{name: "Resource I", id: "I"},
]}
];
this.scheduler.update({resources});
}
render() {
var {...config} = this.state;
return (
<div>
<DayPilotScheduler
{...config}
ref={component => {
this.scheduler = component && component.control;
}}
/>
</div>
);
}
}
export default Scheduler;
React Tutorials
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";
}
}
}