The Vue event calendar adds appointment scheduling to your Vue application. Time runs vertically, with dates or resources displayed as columns, making it useful for weekly agendas, room bookings, and staff schedules.
The component is available in DayPilot Lite (open-source, Apache License 2.0) and DayPilot Pro (commercial). Both include Vue integration and TypeScript declarations.

Vue Calendar Features
DayPilot Lite and Pro
Days or resources as columns. Use day, week, work-week, or custom day views to compare times across dates. With a resource calendar, the columns represent resources instead. The Vue resource example demonstrates that layout with events assigned to resource IDs.
Creating and changing appointments. Select a time range to obtain a new event's start and end. Move an appointment to another time or column, or resize it to change its duration. Use callbacks to open your editor and save changes.
Custom event and cell content. Use Vue templates to render your own text, icons, controls, or components inside the calendar. A template receives the event or cell data, so you can show different content for different items. The examples below demonstrate a Details button, an application-supplied progress value, and conditional icons inside time slots.
Time slots and date navigation. Set business hours, the time-slot duration, and the first day of the week. Connect a Vue date picker or previous/next buttons to the displayed date. Event colors, CSS themes, and locale settings control appearance and date formatting.
Additional DayPilot Pro Features
Grouped and wider resource views. A column-header hierarchy adds group labels above resource columns. Fixed-width columns keep each resource readable and let the user scroll horizontally through the rest.
Time ranges beyond an ordinary day view. Overnight scheduling lets one displayed day continue past midnight; for example, a 22:00–06:00 range stays together. All-day events appear above the hourly grid.
Touch interaction and export. Enable touch scheduling gestures. Export an image, use it in a PDF, or create an Excel spreadsheet. The export guides describe the required libraries and format-specific limits.
See the feature matrix for a detailed edition comparison. For a horizontal timeline with resources as rows, use the Vue Scheduler. A month grid uses the separate Vue Month component.
Render Vue Content Inside Events and Time Slots
![]()
The event-template example adds an SVG icon, a Details button, and a progress bar inside each event. The #event slot receives a DayPilot.Event, so the template can read the event's text and custom fields and attach Vue click handlers. The bar width comes from the example's custom progress field; the Calendar does not calculate that value. Try the event-template demo (Lite).
Cell templates customize the time grid independently of events. The cell-template example prints a slot's start time and uses v-if to place a sun or moon icon in the cell containing a supplied sunrise or sunset time. The #cell slot exposes the interval boundaries; the sample provides the times to compare. This shows how conditional Vue content can be attached to individual slots. Try the cell-template demo (Lite).
Demos and Tutorials
Each tutorial includes a downloadable project. The edition used by the example is shown beside its link.
Views and Navigation
Vue.js Weekly Calendar Tutorial (Open-Source) · Live demo (Lite)
Build a weekly calendar with date navigation and event editing.Vue Resource Calendar (Open-Source) · Live demo (Lite)
Display resources as columns and move events between them.Vue Calendar: Day/Week/Month Views (Open-Source) · Live demo (Lite)
Connect day, week, and month views to shared event data and a date picker.Vue Date Picker with Free/Busy Highlighting (Open-Source) · Live demo (Lite)
Share event data with a date picker and highlight busy dates.
Templates and Advanced Views
Vue Calendar: Using Templates to Add Icons, Buttons, or Progress Bars to Events (Open-Source) · Live demo (Lite)
Use event templates for icons, buttons, and progress indicators.Cell Templates in Vue Calendar: Display Slot Start Times, Sunrise & Sunset (Open-Source) · Live demo (Lite)
Use cell templates to display time labels and conditional sunrise/sunset icons.Vue Scheduler with Vertical Timeline · Live demo (Pro)
Configure the Pro Calendar with a vertical date timeline and resource columns.
Configure a Starter Project
Use Calendar UI Builder to explore settings in a live preview and download a Vue starter. Select the edition that matches your application. Continue adjusting the generated configuration in your own code.
Installation
DayPilot Lite
Install @daypilot/daypilot-lite-vue from npm:
npm install @daypilot/daypilot-lite-vue
DayPilot Pro
At npm.daypilot.org, select Vue and copy the installation command for daypilot-pro-vue. Licensed customers can obtain their package URL in the customer area.
The examples use Vue 3 and the Composition API with <script setup>.
Display a Weekly Appointment Calendar
Start with a Monday-first week and one two-hour meeting.
Calendar.vue
<script setup>
import {ref} from 'vue';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-vue';
const events = ref([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
</script>
<template>
<DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
:weekStarts="1"
:events="events"
/>
</template>
viewType: "Week" displays a week containing startDate. weekStarts: 1 makes Monday the first column. Events use a unique id, display text, and start/end date-times. The meeting ends at 12:00; event ends are exclusive.
The examples use Lite. For Pro, change the package import to daypilot-pro-vue.
See event loading for data formats and loading options.
Navigate and Load Appointments
Previous and Next move by one week. Request appointments for that week, then replace the bound event array with the JSON array returned by your backend.
CalendarLoading.vue
<script setup>
import {ref, watch} from 'vue';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-vue';
const startDate = ref(new DayPilot.Date('2026-10-05'));
const events = ref([]);
watch(startDate, async (_, __, onCleanup) => {
let active = true;
onCleanup(() => { active = false; });
const start = startDate.value;
const end = start.addDays(7);
const url = `/api/events?start=${start}&end=${end}`;
try {
const {data} = await DayPilot.Http.get(url);
if (!active) { return; }
events.value = data;
} catch {
if (active) { await DayPilot.Modal.alert('Could not load data.'); }
}
}, {immediate: true, flush: 'post'});
function navigate(offset) {
startDate.value = startDate.value.addDays(offset * 7);
}
</script>
<template>
<button @click="navigate(-1)">Previous week</button>
<button @click="navigate(1)">Next week</button>
<DayPilotCalendar
:startDate="startDate"
viewType="Week"
:weekStarts="1"
:events="events"
/>
</template>
The /api/events URL represents your own backend. Return items that overlap the requested range: item start is before the requested end, and item end is after the requested start. Failed requests display a DayPilot dialog.
The watcher cleanup prevents an older response from replacing data after another navigation action.
Create Appointments by Selecting Time
This complete variation of the first example handles time range selection. The selection supplies the dates; the dialog supplies the name.
CalendarCreation.vue
<script setup>
import {ref} from 'vue';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-vue';
const events = ref([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
async function onTimeRangeSelected(args) {
const modal = await DayPilot.Modal.prompt('Appointment name:', 'New appointment');
args.control.clearSelection();
if (modal.canceled) { return; }
args.control.events.add({
id: DayPilot.guid(), text: modal.result,
start: args.start, end: args.end
});
}
</script>
<template>
<DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
:weekStarts="1"
:events="events"
@timeRangeSelected="onTimeRangeSelected"
/>
</template>
Canceling the dialog leaves the data unchanged. events.add() inserts the new event locally. In an application with a backend, create the record with a POST request and use the returned ID before adding it to the view.
Move, Resize and Save Events
Moving changes the event position; resizing changes its duration. Both work in the first example without extra configuration. The component updates the display and the supplied data object automatically.
Use the callbacks after the edit to persist the result. This example sends the changed record to the backend; it does not reload the collection after each drag.
CalendarSaving.vue
<script setup>
import {ref} from 'vue';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-vue';
const events = ref([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
async function saveEvent(data) {
try {
await DayPilot.Http.put(`/api/events/${data.id}`, data);
} catch {
await DayPilot.Modal.alert('The change could not be saved.');
}
}
</script>
<template>
<DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
:weekStarts="1"
:events="events"
@eventMoved="saveEvent($event.e.data)"
@eventResized="saveEvent($event.e.data)"
/>
</template>
The /api/events/{id} endpoint accepts the updated JSON record. A failed save is reported while the local edit remains visible; add retry or rollback behavior to suit your application. To disable an interaction, set eventMoveHandling or eventResizeHandling to "Disabled".
Handle an Event Click
To display the clicked item’s name, add this listener to the existing component tag:
@eventClick="DayPilot.Modal.alert(DayPilot.Util.escapeHtml($event.e.text()))"
DayPilot.Modal.alert() accepts HTML. escapeHtml() displays the item’s name as plain text.
Render Custom Vue Content
This independent variation of the first example adds a scoped slot for the event content.
CalendarContent.vue
<script setup>
import {ref} from 'vue';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-vue';
const events = ref([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
</script>
<template>
<DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
:weekStarts="1"
:events="events"
>
<template #event="{event}">
<strong>{{ event.text() }}</strong>
</template>
</DayPilotCalendar>
</template>
Calendar supports event, cell, columnHeader and timeHeader templates. The event slot receives a DayPilot.Event; the cell slot supplies start/end dates.
In Pro, templates also track reactive parent data: changing a value used inside a template refreshes its content automatically. The wrapper handles mounting and cleanup of template content.
Access the Calendar API
Use the event collection API to find and rename the meeting. The wrapper reference, button and handler are shown together.
CalendarApi.vue
<script setup>
import {ref} from 'vue';
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-vue';
const calendar = ref(null);
const events = ref([
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
]);
async function renameEvent() {
const control = calendar.value.control;
const event = control.events.find('meeting');
const modal = await DayPilot.Modal.prompt('Event name:', event.text());
if (modal.canceled) { return; }
event.text(modal.result);
control.events.update(event);
}
</script>
<template>
<button @click="renameEvent">Rename meeting</button>
<DayPilotCalendar
startDate="2026-10-05"
viewType="Week"
:weekStarts="1"
:events="events"
ref="calendar"
/>
</template>
The Vue template ref exposes the underlying control as calendar.value.control. The wrapper creates and disposes it. See the DayPilot.Calendar API for methods, properties and callbacks.
Availability
Availability of this feature in DayPilot editions:
| Product | Lite | Pro |
|---|---|---|
| DayPilot for JavaScript | ||
| DayPilot for ASP.NET WebForms | ||
| DayPilot for ASP.NET MVC | ||
| DayPilot for Java |
DayPilot