DayPilot Angular Calendar is an interactive calendar component for appointment booking, room and equipment reservations, staff schedules, and timetables. Time runs vertically, with days or resources displayed as columns. You can start with a day or week view and add date navigation, drag-and-drop editing, and the event details your application needs.

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 Event Calendar Component (DayPilot)

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

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 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

Editing, Appearance, and Layout

Backend Integration and Specialized Schedules

  • Angular Appointment Calendar with PHP/MySQL (Lite)
    A complete example of loading appointments and saving changes through a REST API. Its Angular scaffolding predates the standalone setup below; use it for the backend workflow and adapt the project setup to your application.

  • 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 configurator

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.

Availability

Availability of this feature in DayPilot editions:

ProductLitePro
DayPilot for JavaScript
DayPilot for ASP.NET WebForms
DayPilot for ASP.NET MVC
DayPilot for Java