Features
JavaScript Scheduler component configured to display a resource context menu on right click.
Hover context menu icon as a hint.
Allows implementing resource/row actions, such as Edit, Delete, and Add Child.
Simple HTML5/JavaScript project for download.
Includes a trial version of DayPilot Pro for JavaScript (see License below)
License
Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript.
Context Menu for JavaScript Scheduler Rows

The Scheduler includes built-in support for row header context menu. It lets you define custom actions for individual resources/rows. In this sample, the menu contains three commands:
Edit...
Delete
Add Child...
The context menu can be created using DayPilot.Menu class. The items array defines the menu commands and their onClick handlers:
const contextMenuResource = new DayPilot.Menu({
items: [
{
text: "Edit...",
onClick: async (args) => {
await app.editResource(args.source);
},
},
{
text: "Delete",
onClick: (args) => {
app.deleteResource(args.source);
},
},
{
text: "-",
},
{
text: "Add Child...",
onClick: async (args) => {
await app.addChildResource(args.source);
},
},
],
});The sample keeps the actual row operations inside a small app object so the menu callbacks stay short. The behavior is straightforward:
app.editResource()opensDayPilot.Modal.prompt(), updatesrow.data.name, and refreshes the Scheduler.app.deleteResource()removes the selected row usingscheduler.rows.remove().app.addChildResource()inserts a nested row usingscheduler.rows.addChild()and then expands the parent row.
To let the sample create nested rows, the Scheduler is configured with treeEnabled: true.
In order to link the menu to row header items, assign the DayPilot.Menu instance to the Scheduler contextMenuResource property.
Context Menu Icon using Active Areas

In order to provide a visible hint that the row context menu is available, we can add a hover button to the row header using a row header active area.
The button is generated in the onBeforeRowHeaderRender event handler. It uses the current builder-template SVG icon set and the special action: "ContextMenu" value so it opens the same menu as the right-click action:
const startDate = DayPilot.Date.today().firstDayOfMonth();
const scheduler = new DayPilot.Scheduler("dp", {
startDate,
days: startDate.daysInMonth(),
rowHeaderWidth: 140,
treeEnabled: true,
scale: "Day",
timeHeaders: [{ groupBy: "Month" }, { groupBy: "Day", format: "d" }],
contextMenuResource,
onBeforeRowHeaderRender: (args) => {
args.row.areas = [
{
right: 6,
top: 9,
width: 20,
height: 20,
symbol: "icons/daypilot.svg#minichevron-down-2",
style: "background-color: #ffffff; color: #4b5563; border: 1px solid #cbd5e1; border-radius: 10px; box-sizing: border-box; padding: 0px;",
visibility: "Hover",
action: "ContextMenu",
},
];
},
});The symbol property points to the minichevron-down-2 icon inside icons/daypilot.svg, which is included in the current JavaScript builder template.
Activated the context menu:
![]()
Full Source Code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JavaScript Scheduler: Resource Context Menu</title>
<style type="text/css">
p, body, td, input, select, button { font-family: -apple-system,system-ui,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif; font-size: 14px; }
body { padding: 0px; margin: 0px; background-color: #ffffff; }
a { color: #1155a3; }
.space { margin: 10px 0px 10px 0px; }
.header { background: #003267; background: linear-gradient(to right, #011329 0%,#00639e 44%,#011329 100%); padding:20px 10px; color: white; box-shadow: 0px 0px 10px 5px rgba(0,0,0,0.75); }
.header a { color: white; }
.header h1 a { text-decoration: none; }
.header h1 { padding: 0px; margin: 0px; }
.main { padding: 10px; margin-top: 10px; }
.generated { color: #999; }
.generated a { color: #999; }
</style>
<!-- DayPilot library -->
<script src="js/daypilot/daypilot-all.min.js"></script>
</head>
<body>
<div class="header">
<h1><a href='https://code.daypilot.org/92781/javascript-scheduler-resource-context-menu'>JavaScript Scheduler: Resource Context Menu</a></h1>
<div><a href="https://javascript.daypilot.org/">DayPilot for JavaScript</a> - HTML5 Calendar/Scheduling Components for JavaScript/Angular/React/Vue</div>
</div>
<div class="main">
<div id="dp"></div>
<div class="generated">Generated using <a href="https://builder.daypilot.org/">DayPilot UI Builder</a>.</div>
</div>
<script>
const app = {
async editResource(row) {
const modal = await DayPilot.Modal.prompt("Resource name:", row.data.name);
if (modal.canceled || !modal.result) {
return;
}
row.data.name = modal.result;
scheduler.update();
scheduler.message("Resource updated");
},
deleteResource(row) {
scheduler.rows.remove(row);
scheduler.message("Resource deleted");
},
async addChildResource(row) {
const modal = await DayPilot.Modal.prompt("Resource name:", "New Resource");
if (modal.canceled || !modal.result) {
return;
}
scheduler.rows.addChild(row, {
name: modal.result,
id: DayPilot.guid(),
});
row.expand();
scheduler.message("Child resource added");
},
loadData() {
const resources = [
{
name: "Manufacturing",
id: "MFG",
expanded: true,
children: [
{ name: "Line 1", id: "R1" },
{ name: "Line 2", id: "R2" },
],
},
{ name: "Quality Control", id: "R3" },
{ name: "Packaging", id: "R4" },
{ name: "Shipping", id: "R5" },
{ name: "Research", id: "R6" },
];
scheduler.update({ resources, events: [] });
},
init() {
scheduler.init();
this.loadData();
},
};
const contextMenuResource = new DayPilot.Menu({
items: [
{
text: "Edit...",
onClick: async (args) => {
await app.editResource(args.source);
},
},
{
text: "Delete",
onClick: (args) => {
app.deleteResource(args.source);
},
},
{
text: "-",
},
{
text: "Add Child...",
onClick: async (args) => {
await app.addChildResource(args.source);
},
},
],
});
const startDate = DayPilot.Date.today().firstDayOfMonth();
const scheduler = new DayPilot.Scheduler("dp", {
startDate,
days: startDate.daysInMonth(),
rowHeaderWidth: 140,
treeEnabled: true,
scale: "Day",
timeHeaders: [{ groupBy: "Month" }, { groupBy: "Day", format: "d" }],
contextMenuResource,
onBeforeRowHeaderRender: (args) => {
args.row.areas = [
{
right: 6,
top: 9,
width: 20,
height: 20,
symbol: "icons/daypilot.svg#minichevron-down-2",
style: "background-color: #ffffff; color: #4b5563; border: 1px solid #cbd5e1; border-radius: 10px; box-sizing: border-box; padding: 0px;",
visibility: "Hover",
action: "ContextMenu",
},
];
},
});
app.init();
</script>
</body>
</html>History
April 11, 2026: Refreshed the sample to the current JavaScript Scheduler version, updated the code examples to modern JavaScript.
DayPilot




