Overview
In this Vue Scheduler tutorial, you will learn how to work with holidays:
How to define global and per-resource holidays.
How to display the holidays using custom Scheduler cell background color.
How to disable drag and drop for the holiday cells.
The attached project includes a trial version of DayPilot Pro for JavaScript (see License below).
For an introduction to using the Vue Scheduler component, please see the following tutorial:
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.
How to display global holidays in Vue Scheduler?
First, you need to define the global holidays. We will use a new globalHolidays
property which holds an array with holiday dates. Each item specifies a date range, defined using start
and end
dates. The end
date specifies the last day of the holiday (we need to take it into account later when checking the date range, see below).
The following example defines a holiday for August 9, 2021:
globalHolidays: [
{ start: "2025-08-09", end: "2025-08-09", backColor: "#b6d7a8", headerColor: "#6aa84f"}
],
Now you need to configure the Vue Scheduler component to highlight the grid cells that overlap any of the holiday date ranges.
You can customize the Vue Scheduler cells using onBeforeCellRender
event handler. This event handler is called once for each of the Scheduler cells. You can use it to set custom background color and other properties.
In the event handler, we will check if the cell date (args.cell.start
and args.cell.end
) overlaps with the global holidays.
const start = new DayPilot.Date(holiday.start);
const end = new DayPilot.Date(holiday.end).addDays(1);
const overlaps = DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
Note that we have added 1 day to the end date. The DayPilot.Util.overlaps()
method works with exact time points. Our end date ("2025-08-09"
) is interpreted as the start of August 9, 2025 (ie. "2025-08-09T00:00:00"
). In order to treat it as the end of August 9, 2025, you need to add one day using addDays(1)
. That will result in "2025-08-10T00:00:00"
, which is the time point we need.
If an overlap is detected, we set a custom background color using args.cell.backColor
property.
The following code will highlight the holidays defined in the globalHolidays
property:
<template>
<DayPilotScheduler :config="config" ref="schedulerRef" />
</template>
<script setup>
import { ref, reactive } from 'vue';
import { DayPilot, DayPilotScheduler } from 'daypilot-pro-vue';
const globalHolidays = ref([
{ start: "2025-08-09", end: "2025-08-09", backColor: "#b6d7a8", headerColor: "#6aa84f" }
]);
const config = reactive({
onBeforeCellRender: (args) => {
highlightGlobalHolidays(args);
},
// ...
});
const highlightGlobalHolidays = (args) => {
const item = globalHolidays.value.find(holiday => {
const start = new DayPilot.Date(holiday.start);
const end = new DayPilot.Date(holiday.end).addDays(1);
return DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
});
if (item) {
args.cell.backColor = item.backColor;
}
};
const schedulerRef = ref(null);
// ...
</script>
How to highlight global holidays in the Vue Scheduler time header?
You can also highlight the global holidays in the Vue Scheduler time header. Note the green bar displayed in the time header cell for August 9, 2021:
To highlight the holidays in the time header, you can use the onBeforeTimeHeaderRender
event handler, which lets you customize the appearance of the time headers cells.
The logic is very similar - you need to check for overlaps of the time header cell start and end with the global holiday dates.
This time, we will not highlight the whole cell using the backColor
property but we will add a small bar at the bottom of the time header cell using active areas:
const config = reactive({
onBeforeTimeHeaderRender: (args) => {
if (args.header.level === 1) {
const item = globalHolidays.value.find(function (range) {
const start = new DayPilot.Date(range.start);
const end = new DayPilot.Date(range.end).addDays(1);
return DayPilot.Util.overlaps(start, end, args.header.start, args.header.end);
});
if (item) {
const start = new DayPilot.Date(item.start);
const end = new DayPilot.Date(item.end).addDays(1);
args.header.areas = [
{start: start, end: end, bottom: 0, height: 5, backColor: item.headerColor}
];
}
}
},
// ...
});
How to disable drag and drop operations for holidays?
In the previous example, we have changed the background color of the Scheduler cells but we didn’t change the cell behavior.
If you want to disable the drag and drop operations for the cells marked as holidays, you need to use args.cell.disabled
to mark the cell as disabled:
<template>
<div class="space">
<label><input type="checkbox" v-model="holidaysDisabled" @change="updateDisabled">Disable drag and drop for holidays</label>
</div>
<DayPilotScheduler :config="config" ref="schedulerRef" />
</template>
<script setup>
import { ref, reactive } from 'vue';
import { DayPilot, DayPilotScheduler } from 'daypilot-pro-vue';
const holidaysDisabled = ref(true);
const globalHolidays = ref([
{ start: "2025-08-09", end: "2025-08-09", backColor: "#b6d7a8", headerColor: "#6aa84f" }
]);
const config = reactive({
onBeforeCellRender: (args) => {
highlightGlobalHolidays(args);
}
});
const highlightGlobalHolidays = (args) => {
// ...
const item = globalHolidays.value.find(holiday => {
const start = new DayPilot.Date(holiday.start);
const end = new DayPilot.Date(holiday.end).addDays(1);
return DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
});
if (item) {
// ...
if (holidaysDisabled.value) {
args.cell.disabled = true;
}
}
};
const updateDisabled = () => {
schedulerRef.value.control.update();
};
const schedulerRef = ref(null);
</script>
How to display resource-specific holidays in the Vue Scheduler?
You can also define holidays for specific resources. In this example, we define the holidays using a custom holidays
property of the resources[]
array:
const resources = [
{ name: "Resource A", id: "A"},
{ name: "Resource B", id: "B", holidays: [
{ start: "2025-08-04", end: "2025-08-06", backColor: "#dd7e6b"}
]},
{ name: "Resource C", id: "C"},
{ name: "Resource D", id: "D", holidays: [
{ start: "2025-08-02", end: "2025-08-06", backColor: "#ffe599"}
]},
{ name: "Resource E", id: "E"},
{ name: "Resource F", id: "F"},
{ name: "Resource G", id: "G"},
{ name: "Resource H", id: "H"},
{ name: "Resource I", id: "I"},
{ name: "Resource J", id: "J"},
];
Now, it’s necessary to check the overlaps with the resource holidays in onBeforeCellRender
event handler.
First, you need to get the holiday data. The resource ID is available in args.cell.resource
. To find the resource data object, use the rows.find() method:
const row = scheduler.rows.find(args.cell.resource);
const holidays = row.data.holidays;
The next step is to check for overlaps with the resource holiday dates:
<template>
<DayPilotScheduler :config="config" ref="schedulerRef" />
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { DayPilot, DayPilotScheduler } from 'daypilot-pro-vue';
const holidaysDisabled = ref(true);
const config = reactive({
onBeforeCellRender: (args) => {
// ...
highlightResourceHolidays(args);
}
});
const schedulerRef = ref(null);
const highlightResourceHolidays = (args) => {
const row = schedulerRef.value.control.rows.find(args.cell.resource);
const holidays = row.data.holidays;
if (!holidays) {
return;
}
const item = holidays.find(holiday => {
const start = new DayPilot.Date(holiday.start);
const end = new DayPilot.Date(holiday.end).addDays(1);
return DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
});
if (item) {
args.cell.backColor = item.backColor;
if (holidaysDisabled.value) {
args.cell.disabled = true;
}
}
};
const loadResources = () => {
const resources = [
{ name: "Resource A", id: "A" },
{ name: "Resource B", id: "B", holidays: [
{ start: "2025-08-04", end: "2025-08-06", backColor: "#dd7e6b" }
] },
{ name: "Resource C", id: "C" },
{ name: "Resource D", id: "D", holidays: [
{ start: "2025-08-02", end: "2025-08-06", backColor: "#ffe599" }
] },
{ name: "Resource E", id: "E" },
{ name: "Resource F", id: "F" },
{ name: "Resource G", id: "G" },
{ name: "Resource H", id: "H" },
{ name: "Resource I", id: "I" },
{ name: "Resource J", id: "J" },
];
config.resources = resources;
};
onMounted(() => {
loadResources();
});
</script>
Full Source Code
And here is the full source code for the Vue Scheduler example which highlights global and resource-specific holidays in the Scheduler grid, with an option to disable drag and drop for the holidays.
<template>
<div class="space">
<label><input type="checkbox" v-model="holidaysDisabled" @change="updateDisabled">Disable drag and drop for holidays</label>
</div>
<DayPilotScheduler :config="config" ref="schedulerRef" />
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { DayPilot, DayPilotScheduler } from 'daypilot-pro-vue';
const holidaysDisabled = ref(false);
const globalHolidays = ref([
{ start: "2025-08-09", end: "2025-08-09", backColor: "#b6d7a8", headerColor: "#6aa84f" }
]);
const schedulerRef = ref(null);
const config = reactive({
timeHeaders: [{ "groupBy": "Month" }, { "groupBy": "Day", "format": "d" }],
scale: "Day",
startDate: "2025-08-01",
days: 31,
timeRangeSelectedHandling: "Enabled",
durationBarVisible: false,
onTimeRangeSelected: async (args) => {
const scheduler = args.control;
const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
scheduler.clearSelection();
if (modal.canceled) {
return;
}
scheduler.events.add({
start: args.start,
end: args.end,
id: DayPilot.guid(),
resource: args.resource,
text: modal.result
});
},
treeEnabled: true,
onBeforeTimeHeaderRender: (args) => {
if (args.header.level === 1) {
const item = globalHolidays.value.find(function (range) {
const start = new DayPilot.Date(range.start);
const end = new DayPilot.Date(range.end).addDays(1);
return DayPilot.Util.overlaps(start, end, args.header.start, args.header.end);
});
if (item) {
const start = new DayPilot.Date(item.start);
const end = new DayPilot.Date(item.end).addDays(1);
args.header.areas = [
{start: start, end: end, bottom: 0, height: 5, backColor: item.headerColor}
];
}
}
},
onBeforeCellRender: (args) => {
// highlightResourceHolidays(args);
highlightGlobalHolidays(args);
}
});
const updateDisabled = () => {
schedulerRef.value.control.update();
};
const highlightGlobalHolidays = (args) => {
const item = globalHolidays.value.find(holiday => {
const start = new DayPilot.Date(holiday.start);
const end = new DayPilot.Date(holiday.end).addDays(1);
return DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
});
if (item) {
args.cell.backColor = item.backColor;
if (holidaysDisabled.value) {
args.cell.disabled = true;
}
}
};
const highlightResourceHolidays = (args) => {
const scheduler = args.control;
const row = scheduler.rows.find(args.cell.resource);
const holidays = row.data.holidays;
if (!holidays) {
return;
}
const item = holidays.find(holiday => {
const start = new DayPilot.Date(holiday.start);
const end = new DayPilot.Date(holiday.end).addDays(1);
return DayPilot.Util.overlaps(start, end, args.cell.start, args.cell.end);
});
if (item) {
args.cell.backColor = item.backColor;
if (holidaysDisabled.value) {
args.cell.disabled = true;
}
}
};
const loadEvents = () => {
const events = [
{id: 1, start: "2025-08-01T00:00:00", end: "2025-08-05T00:00:00", text: "Event 1", resource: "R1"},
];
config.events = events;
};
const loadResources = () => {
const resources = [
{name: "Resource A", id: "A"},
{
name: "Resource B", id: "B", holidays: [
{start: "2025-08-04", end: "2025-08-06", backColor: "#dd7e6b"}
]
},
{name: "Resource C", id: "C"},
{
name: "Resource D", id: "D", holidays: [
{start: "2025-08-02", end: "2025-08-06", backColor: "#ffe599"}
]
},
{name: "Resource E", id: "E"},
{name: "Resource F", id: "F"},
{name: "Resource G", id: "G"},
{name: "Resource H", id: "H"},
{name: "Resource I", id: "I"},
{name: "Resource J", id: "J"},
];
config.resources = resources;
};
onMounted(() => {
loadResources();
loadEvents();
schedulerRef.value?.control.message("Welcome!");
});
</script>
<style>
.scheduler_default_event,
.scheduler_default_event_inner {
border-radius: 25px;
}
body .scheduler_default_event_inner {
background: #42a5f5;
color: #ffffff;
border: 1px solid #1e88e5;
padding-left: 10px;
}
</style>
You can download a complete Vue 3 project at the top of the article.