DayPilot Angular Calendar displays events on a vertical time axis, with columns for days or resources. A week view shows appointments across seven days; a resource view compares the schedules of several people or rooms on the same date. Users can select a time range, move an event to another column, or resize it to change its duration.
The component is available in DayPilot Lite, the open-source edition under the Apache License 2.0, and DayPilot Pro, the commercial edition with additional scheduling features. Both provide Angular components, TypeScript definitions, and bindings for configuration and event data.
Try the Angular calendar demo · Get the starter project · Configure a calendar in UI Builder

Angular Calendar Features
The day and week layouts work well when users need to see the timing and duration of appointments. A resource calendar uses the same vertical time axis to compare bookings for several people, rooms, or machines side by side.
DayPilot Lite and Pro
Day, work-week, week, and custom day views. Choose the calendar view and number of days to display. Combine Calendar with the Angular monthly calendar when your application needs a month overview as well.
Resources as columns. Display a daily schedule for staff, rooms, or equipment using the resource calendar. Each event belongs to a resource column, and users can move it to a different resource.
Interactive event editing. Let users select a time range to create an event, then move or resize it using drag and drop. Handle these actions in Angular callbacks to open an editor, update your application state, and save changes to your backend.
Event appearance and CSS themes. Use colors, labels, and event actions to make different types of appointments easy to recognize. Event customization, cell customization, and CSS themes let you adapt the calendar to your application.
Working hours and date formatting. Set business hours, time-slot duration, and the first day of the week. Use a locale to format dates and times for your users.
Date navigation and Angular state. Connect an Angular date picker, add previous/next buttons, and load events for the selected period. Bind options and event data using signals or ordinary objects and arrays.
Additional DayPilot Pro Features
Grouped resource headers. Organize rooms by location, staff by team, or resources under individual days with a column hierarchy. Try the grouped-column demo.
Wide resource schedules. Keep columns readable at a fixed width and use horizontal scrolling to reach additional resources. Try the 50-column demo.
Overnight schedules. Display a working day that crosses midnight, such as a night shift or television schedule. See overnight scheduling and the live demo.
All-day events and touch interaction. Display all-day events above the time grid and support scheduling gestures on touch devices.
Export. Export the calendar as an image, use the image in a PDF document, or create an Excel spreadsheet. The export guides describe the required libraries and format-specific limits. Try the Excel export demo.
The Pro demos above show the underlying JavaScript Calendar features that you can configure through the Angular component. For the complete edition comparison, see the feature matrix. If you need time to run horizontally with resources as rows, see the Angular Scheduler.
Angular Calendar Examples
Undo and Redo Calendar Edits (Lite)
Calendar callbacks let an Angular application respond to individual edits and keep a history of changes. The undo/redo tutorial records event creation, movement, resizing, and deletion in an application service. Each record stores the event's previous and current data, so Undo can restore the previous dates or bring back a deleted event. Redo applies the recorded change again.
The service starts with a snapshot of the loaded events and controls whether the Undo and Redo buttons are enabled. The Calendar supplies the editing callbacks and event add/update/remove methods; the tutorial supplies the history and replay logic. In the live demo, move the sample event, undo the move, and redo it to see the event and history position change together.

The tutorial keeps the action history in an Angular service and updates the Calendar when an action is undone or redone.
Combine Text and Event-Type Filters (Pro)
The event-filtering example combines a case-insensitive text search with a Reservation/Maintenance selector. An event stays visible only when it matches both criteria. For example, choosing Maintenance and entering part of an event name narrows the view to maintenance events with that text.
The Angular controls pass the criteria to events.filter(); onEventFilter applies the application's matching rules to each event. The custom type field also controls event color and the Maintenance label. Clearing the filters restores the loaded events without fetching or recreating them. Try the combined filters.
Angular Calendar Demos and Tutorials
Explore the live examples before adding the component to your application. Each tutorial explains the implementation and provides a downloadable Angular project. The edition is shown for each example so you can start with the package you plan to use.
Calendar Views and Date Navigation
Angular Calendar with Day/Week/Month Views : Live demo (Lite)
A starting point for an application with day, week, and month buttons and a date picker. It combines Calendar, Month, and Navigator components, with a shared event source across the views.Angular Resource Calendar : Live demo (Lite)
Schedule events for resources displayed as columns. See resource columns, event actions, and custom column headers in a vertical daily schedule.Angular Calendar: Date Switching : Live demo (Lite)
Connect a date picker to the calendar and add previous/next navigation. This is a focused example of keeping the selected date and displayed week together.Angular Date Picker with Drag-and-Drop Range Selection : Live demo (Lite)
Let users select a custom date range in the Navigator and display that range in the Calendar, instead of always showing a fixed week.
Editing, Appearance, and Layout
Angular Calendar with Undo/Redo : Live demo (Lite)
Add an application-managed history for event creation, movement, resizing, and deletion. The tutorial shows how to build undo/redo controls around Calendar callbacks.Angular Calendar: CSS Themes : Live demo (Lite)
Compare calendar themes and switch them at runtime. Use this example to explore styling without changing the scheduling data or Angular bindings.Angular Calendar: Event Filtering : Live demo (Pro)
Combine text and event-type filters to choose the events displayed in the calendar. See how the Calendar filtering API works with Angular state.Angular Calendar: Full Screen Layout : Live demo (Pro)
Make the calendar fill the available application window, with a collapsible date-picker sidebar. Useful when the schedule is the main working area of the application.Angular Calendar: Detect Orientation Change : Live demo (Pro)
Change the calendar layout when the screen switches between portrait and landscape. Explore how an Angular application can adapt the visible schedule to its available space.
Backend Integration and Specialized Schedules
Angular Appointment Calendar with PHP/MySQL (Lite)
Load appointments and save creation, edits, moves, and deletion through a PHP API. The current project uses standalone Angular components and signals, with SQLite or MySQL storage.Angular Timetable (Pro)
Build a weekly timetable with custom time blocks and labels. The tutorial uses an older Angular project structure but illustrates a specialized Calendar layout.Angular Calendar: Displaying a Custom Set of Days (Pro)
Display a selected set of dates as columns, including non-consecutive dates. This example uses an older Angular project structure; the column configuration is the main pattern to reuse.
Configure an Angular Calendar Visually
Calendar UI Builder lets you change the calendar's appearance and behavior while seeing the result immediately. Select an Angular target and the edition you want to use, then download a starter project with your configuration. You can continue editing the options in TypeScript after downloading the project.
Installation
DayPilot Lite
Install @daypilot/daypilot-lite-angular from npm:
npm install @daypilot/daypilot-lite-angular
DayPilot Pro
At npm.daypilot.org, select Angular and copy the installation command for daypilot-pro-angular. Licensed customers can obtain their package URL in the customer area.
The examples use standalone Angular components. Import DayPilotModule in the component that contains the DayPilot tag.
Display a Weekly Appointment Calendar
Start with a Monday-first week and one two-hour meeting.
calendar.component.ts
import {Component} from '@angular/core';
import {DayPilot, DayPilotModule} from '@daypilot/daypilot-lite-angular';
@Component({
selector: 'app-calendar',
standalone: true,
imports: [DayPilotModule],
template: `
<daypilot-calendar
[config]="config"
[events]="events"></daypilot-calendar>
`
})
export class CalendarComponent {
config: DayPilot.CalendarConfig = {
startDate: '2026-10-05',
viewType: 'Week',
weekStarts: 1
};
events: DayPilot.EventData[] = [
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
];
}
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.
Import CalendarComponent in the parent component and use <app-calendar></app-calendar> in its template.
The examples use Lite. For Pro, change the package import to daypilot-pro-angular.
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.
calendar-loading.component.ts
import {Component, ChangeDetectorRef, inject, OnInit} from '@angular/core';
import {DayPilot, DayPilotModule} from '@daypilot/daypilot-lite-angular';
@Component({
selector: 'app-calendar',
standalone: true,
imports: [DayPilotModule],
template: `
<button (click)="navigate(-1)">Previous week</button>
<button (click)="navigate(1)">Next week</button>
<daypilot-calendar
[config]="config"
[events]="events"></daypilot-calendar>
`
})
export class CalendarComponent implements OnInit {
config: DayPilot.CalendarConfig = {
startDate: '2026-10-05',
viewType: 'Week',
weekStarts: 1
};
events: DayPilot.EventData[] = [];
private changes = inject(ChangeDetectorRef);
private loadRequest = 0;
ngOnInit() {
this.loadData();
}
navigate(offset: number) {
const start = new DayPilot.Date(this.config.startDate!).addDays(offset * 7);
this.config = {...this.config, startDate: start};
this.loadData();
}
async loadData() {
const request = ++this.loadRequest;
const start = new DayPilot.Date(this.config.startDate!);
const end = start.addDays(7);
const url = `/api/events?start=${start}&end=${end}`;
try {
const {data} = await DayPilot.Http.get(url);
if (request !== this.loadRequest) { return; }
this.events = data;
this.changes.markForCheck();
} catch {
if (request === this.loadRequest) {
await DayPilot.Modal.alert('Could not load data.');
}
}
}
}
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 request counter 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.
calendar-creation.component.ts
import {Component} from '@angular/core';
import {DayPilot, DayPilotModule} from '@daypilot/daypilot-lite-angular';
@Component({
selector: 'app-calendar',
standalone: true,
imports: [DayPilotModule],
template: `
<daypilot-calendar
[config]="config"
[events]="events"></daypilot-calendar>
`
})
export class CalendarComponent {
config: DayPilot.CalendarConfig = {
startDate: '2026-10-05',
viewType: 'Week',
weekStarts: 1,
onTimeRangeSelected: async 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
});
}
};
events: DayPilot.EventData[] = [
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
];
}
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.
calendar-saving.component.ts
import {Component} from '@angular/core';
import {DayPilot, DayPilotModule} from '@daypilot/daypilot-lite-angular';
@Component({
selector: 'app-calendar',
standalone: true,
imports: [DayPilotModule],
template: `
<daypilot-calendar
[config]="config"
[events]="events"></daypilot-calendar>
`
})
export class CalendarComponent {
config: DayPilot.CalendarConfig = {
startDate: '2026-10-05',
viewType: 'Week',
weekStarts: 1,
onEventMoved: args => this.saveEvent(args.e.data),
onEventResized: args => this.saveEvent(args.e.data)
};
events: DayPilot.EventData[] = [
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
];
async saveEvent(data: DayPilot.EventData) {
try {
await DayPilot.Http.put(`/api/events/${data.id}`, data);
} catch {
await DayPilot.Modal.alert('The change could not be saved.');
}
}
}
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 a Event Click
To display the clicked item’s name, add this callback to config:
onEventClick: args => DayPilot.Modal.alert(DayPilot.Util.escapeHtml(args.e.text()))
DayPilot.Modal.alert() accepts HTML. escapeHtml() displays the item’s name as plain text.
Access the Calendar API
Use the event collection API to find and rename the meeting. The wrapper reference, button and handler are shown together.
calendar-api.component.ts
import {Component, ViewChild} from '@angular/core';
import {
DayPilot, DayPilotModule, DayPilotCalendarComponent
} from '@daypilot/daypilot-lite-angular';
@Component({
selector: 'app-calendar',
standalone: true,
imports: [DayPilotModule],
template: `
<button (click)="renameEvent()">Rename meeting</button>
<daypilot-calendar
#calendar
[config]="config"
[events]="events"></daypilot-calendar>
`
})
export class CalendarComponent {
@ViewChild('calendar') calendar!: DayPilotCalendarComponent;
config: DayPilot.CalendarConfig = {
startDate: '2026-10-05',
viewType: 'Week',
weekStarts: 1
};
events: DayPilot.EventData[] = [
{id: 'meeting', text: 'Meeting',
start: '2026-10-05T10:00:00', end: '2026-10-05T12:00:00'}
];
async renameEvent() {
const control = this.calendar.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);
}
}
@ViewChild provides the wrapper; its control property exposes the underlying JavaScript component after initialization. The wrapper creates and disposes it. See the DayPilot.Calendar API for methods, properties and callbacks.
Load Data into Signal Inputs
If your application stores the collection in an Angular signal, pass that signal to the same input. This standalone variation loads data and calls set(); the wrapper observes the new collection.
calendar-signal-loading.component.ts
import {Component, OnInit, signal} from '@angular/core';
import {DayPilot, DayPilotModule} from '@daypilot/daypilot-lite-angular';
@Component({
selector: 'app-calendar',
standalone: true,
imports: [DayPilotModule],
template: `
<button (click)="navigate(-1)">Previous week</button>
<button (click)="navigate(1)">Next week</button>
<daypilot-calendar
[config]="config"
[events]="events"></daypilot-calendar>
`
})
export class CalendarComponent implements OnInit {
config: DayPilot.CalendarConfig = {
startDate: '2026-10-05',
viewType: 'Week',
weekStarts: 1
};
events = signal<DayPilot.EventData[]>([]);
private loadRequest = 0;
ngOnInit() {
this.loadData();
}
navigate(offset: number) {
const start = new DayPilot.Date(this.config.startDate!).addDays(offset * 7);
this.config = {...this.config, startDate: start};
this.loadData();
}
async loadData() {
const request = ++this.loadRequest;
const start = new DayPilot.Date(this.config.startDate!);
const end = start.addDays(7);
const url = `/api/events?start=${start}&end=${end}`;
try {
const {data} = await DayPilot.Http.get(url);
if (request !== this.loadRequest) { return; }
this.events.set(data);
} catch {
if (request === this.loadRequest) {
await DayPilot.Modal.alert('Could not load data.');
}
}
}
}
Bind the signal itself with [events]="events". Binding its current value with () instead uses the ordinary input path. Keep one form consistently. Signals require Angular 16 or later.
Signal configuration/event inputs are supported since DayPilot Pro 2025.1.6377 and DayPilot Lite Angular 5.0.0.
Customize Content with Angular Templates (Pro)
Use Angular markup for Calendar events, time cells, column headers, and time headers. Each template receives the item being rendered, so it can show appointment details or custom labels using Angular bindings.
This template integration is available in DayPilot Pro for Angular since version 2026.4.7099. Install the corresponding daypilot-pro-angular package from npm.daypilot.org.
Import DayPilotModule from daypilot-pro-angular in the Angular component that owns the template. It exports the DayPilot component and the daypilotTemplate directive. Place a named ng-template directly inside <daypilot-calendar>. Templates support Angular interpolation, bindings, event handlers, and child components; import any child components or additional Angular directives you use in the containing component.
Template Example
This standalone example supplies the component configuration and data as well as the template markup.
import {Component} from '@angular/core';
import {DayPilot, DayPilotModule} from 'daypilot-pro-angular';
@Component({
selector: 'app-calendar-templates',
standalone: true,
imports: [DayPilotModule],
template: `
<daypilot-calendar [config]="config" [events]="events">
<ng-template daypilotTemplate="event"
daypilotTemplateFor="calendar" let-event="event">
<strong>{{ event.text() }}</strong>
</ng-template>
<ng-template daypilotTemplate="cell"
daypilotTemplateFor="calendar" let-cell="cell">
<small>{{ cell.start.toString('H:mm') }}</small>
</ng-template>
<ng-template daypilotTemplate="columnHeader"
daypilotTemplateFor="calendar" let-column="column">
<strong>{{ column.name }}</strong>
</ng-template>
<ng-template daypilotTemplate="timeHeader"
daypilotTemplateFor="calendar" let-header="header">
{{ header.hours }}:{{ header.minutes === 0 ? '00' : header.minutes }}
</ng-template>
</daypilot-calendar>
`
})
export class CalendarTemplatesComponent {
config: DayPilot.CalendarConfig = {
startDate: '2026-10-05',
viewType: 'Week'
};
events: DayPilot.EventData[] = [
{id: 1, text: 'Planning',
start: '2026-10-05T09:00:00', end: '2026-10-05T10:30:00'}
];
}
The example uses all four supported templates. Keep only the templates you need. Calendar time headers expose hours and minutes; they do not use the Scheduler time-header context with date objects and a level.
Supported Templates and Context
Each entry lists a supported daypilotTemplate name and its context bindings. The let- declarations bind named context values; an unqualified let-item would request an implicit value, which these templates do not provide.
event:let-event="event".The DayPilot.Event displayed in the event element.
cell:let-cell="cell".An object with
startandend(DayPilot.Date),resource(resource ID),column(DayPilot.Column), and numericx/yindices.columnHeader:let-column="column".The DayPilot.Column for the column header.
timeHeader:let-header="header".An object with numeric
hours/minutes,start(string), andtime(DayPilot.Duration).
The optional daypilotTemplateFor="calendar" qualifier selects this component's context for Angular template type checking. It is useful when a name such as cell has different context fields in different components. If specified, it must match the enclosing DayPilot component. Enable Angular's strictTemplates option to check context members while building your application.
Rendering and Application State
Define at most one template for each supported name in a component. A template takes precedence over the corresponding DOM-add callback; omit the template to use that callback instead. Existing DOM-removal callbacks still run.
The wrapper creates and disposes the Angular views as DayPilot renders and removes their elements. Keep values that must survive scrolling, navigation, or redraws in application state, rather than only in a rendered child component.
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