Features

  • Day, week and month calendar views
  • Switch the view using buttons at the top of the page
  • Each view is implemented using a special component - the components are displayed/hidden as needed
  • Date picker to change the visible date
  • The selected view is highlighted in the date picker
  • The date picker highlights busy days using bold font
  • All calendar components and the date picker share the same data source
  • Built using Angular Calendar components from DayPilot Pro for JavaScript package
  • Includes a trial version of DayPilot Pro for JavaScript (see also 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. Buy a license.

Angular Calendar: Multiple Views

We are going to create an Angular application that will display a calendar with multiple views of the same data (day, week, and month).

Each view will be represented by a standalone calendar component instance:

  • day view: DayPilotCalendar component with viewType: "Day" (the default mode)
  • week view: DayPilotCalendar component with viewType: "Week"
  • month view: DayPilotMonth component

Depending on the view type selected by the user, we will show the corresponding calendar component and hide the other ones.

Angular Calendar: Day View

angular-calendar-component-day-view.png

First, we will add the day-view calendar.

  1. The template contains <daypilot-calendar> tag that displays the Angular Calendar component.
  2. The day view loads the configuration from configDay object which is specified using "config" attribute.
  3. The events are loaded from events array (specified using "events" attribute).

The configDay object specifies the viewType ("Day"). You can use this object to specify additional calendar properties and event handlers.

calendar.component.ts

import {Component, ViewChild, AfterViewInit} from "@angular/core";
import {
  DayPilot,
  DayPilotCalendarComponent
} from "daypilot-pro-angular";
import {DataService} from "./data.service";{}

@Component({
  selector: 'calendar-component',
  template: `
    <daypilot-calendar [config]="configDay" [events]="events" #day></daypilot-calendar>
  `
})
export class CalendarComponent implements AfterViewInit {

  @ViewChild("day") day: DayPilotCalendarComponent;

  events: any[] = [];

  configDay: any = {
    viewType: "Day"
  };

  constructor(private ds: DataService) {
  }

  ngAfterViewInit(): void {
    this.loadEvents();
  }

  loadEvents(): void {
    let from = this.day.control.visibleStart();
    let to = this.day.control.visibleEnd();
    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });
  }

  // ...

}

Angular Calendar: Week View

angular-calendar-component-week-view.png

Now we will add the week-view calendar.

  1. The template contains <daypilot-calendar> tag that displays the Angular Calendar component. It's the same calendar component that we used for the day view. This time we have switched it to display a week.
  2. The week view loads the configuration from configWeek object which is specified using "config" attribute.
  3. The events are loaded from events array (specified using "events" attribute).

The configWeek object is also very simple - it only specifies the viewType property ("Week").

Note that we have used the same events object. Both calendars (day and week) now load the same data.

calendar.component.ts

import {Component, ViewChild, AfterViewInit} from "@angular/core";
import {
  DayPilot,
  DayPilotCalendarComponent
} from "daypilot-pro-angular";
import {DataService} from "./data.service";{}

@Component({
  selector: 'calendar-component',
  template: `
    <daypilot-calendar [config]="configWeek" [events]="events" #week></daypilot-calendar>
  `
})
export class CalendarComponent implements AfterViewInit {

  @ViewChild("week") week: DayPilotCalendarComponent;

  events: any[] = [];

  configWeek: any = {
    viewType: "Week"
  };

  constructor(private ds: DataService) {
  }

  ngAfterViewInit(): void {
    this.loadEvents();
  }

  loadEvents(): void {
    let from = this.week.control.visibleStart();
    let to = this.week.control.visibleEnd();
    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });
  }

  // ...

}

Angular Calendar: Month View

angular-calendar-component-month-view.png

The month view is displayed using <daypilot-month> tag which adds the Angular monthly calendar component.

The "config" attribute specifies the config object (configMonth). The "events" attribute points to the same events object that we used for the day and week calendar components.

calendar.component.ts

import {Component, ViewChild, AfterViewInit} from "@angular/core";
import {
  DayPilot,
  DayPilotMonthComponent
} from "daypilot-pro-angular";
import {DataService} from "./data.service";{}

@Component({
  selector: 'calendar-component',
  template: `
    <daypilot-month [config]="configMonth" [events]="events" #month></daypilot-month>
  `
})
export class CalendarComponent implements AfterViewInit {

  @ViewChild("month") month: DayPilotMonthComponent;

  events: any[] = [];

  configMonth: any = {
  };

  constructor(private ds: DataService) {
  }

  ngAfterViewInit(): void {
    this.loadEvents();
  }

  loadEvents(): void {
    let from = this.month.control.visibleStart();
    let to = this.month.control.visibleEnd();
    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });
  }

}

Switching the Views

angular-calendar-component-switching-views.png

In this step, we will add buttons that will let users switch the current view. The calendar components don't have a direct attribute that would let us set the visibility so we need to modify the config object explicitly.

calendar.component.ts

import {Component, ViewChild, AfterViewInit} from "@angular/core";
import {
  DayPilot,
  DayPilotCalendarComponent,
  DayPilotMonthComponent,
  DayPilotNavigatorComponent
} from "daypilot-pro-angular";
import {DataService} from "./data.service";{}

@Component({
  selector: 'calendar-component',
  template: `
    <div class="buttons">
    <button (click)="viewDay()">Day</button>
    <button (click)="viewWeek()">Week</button>
    <button (click)="viewMonth()">Month</button>
    </div>

    <daypilot-calendar [config]="configDay" [events]="events" #day></daypilot-calendar>
    <daypilot-calendar [config]="configWeek" [events]="events" #week></daypilot-calendar>
    <daypilot-month [config]="configMonth" [events]="events" #month></daypilot-month>
  `
})
export class CalendarComponent implements AfterViewInit {

  @ViewChild("day") day: DayPilotCalendarComponent;
  @ViewChild("week") week: DayPilotCalendarComponent;
  @ViewChild("month") month: DayPilotMonthComponent;

  events: any[] = [];

  configDay: any = {
  };

  configWeek: any = {
    viewType: "Week"
  };

  configMonth: any = {
  };

  constructor(private ds: DataService) {
    this.viewWeek();
  }

  ngAfterViewInit(): void {
    // ...
  }

  viewDay():void {
    this.configDay.visible = true;
    this.configWeek.visible = false;
    this.configMonth.visible = false;
  }

  viewWeek():void {
    this.configDay.visible = false;
    this.configWeek.visible = true;
    this.configMonth.visible = false;
  }

  viewMonth():void {
    this.configDay.visible = false;
    this.configWeek.visible = false;
    this.configMonth.visible = true;
  }
}

Date Picker for Switching the Date

angular-calendar-component-day-week-month-date-picker.png

The previous examples didn't specify any date to be displayed - by default all calendar components use today.

We want to let users choose a date to be displayed and so we will add a date picker using DayPilot Navigator component.

The navigator is added using <daypilot-navigator> tag:

<daypilot-navigator [config]="configNavigator" [events]="events" [(date)]="date" (dateChange)="changeDate($event)" #navigator></daypilot-navigator>

The first two attributes ("config" and "events") work the same way - they specify the config object and event data source, respectively.

The navigator exposes date property and dateChange event that will let us specify the selected date and watch the changes.

The selected date will be always available as date property of our CalendarComponent class:

date = DayPilot.Date.today();

This property lets us set the selected date (during the initial load or anytime later).

The changeDate() method updates the startDate property of all linked calendar components which changes the visible date:

changeDate(date: DayPilot.Date): void {
  this.configDay.startDate = date;
  this.configWeek.startDate = date;
  this.configMonth.startDate = date;
}

Source Code

import {Component, ViewChild, AfterViewInit} from "@angular/core";
import {
  DayPilot,
  DayPilotCalendarComponent,
  DayPilotMonthComponent,
  DayPilotNavigatorComponent
} from "daypilot-pro-angular";
import {DataService} from "./data.service";{}

@Component({
  selector: 'calendar-component',
  template: `
    <div class="container">
      <div class="navigator">
        <daypilot-navigator [config]="configNavigator" [events]="events" [(date)]="date" (dateChange)="changeDate($event)" #navigator></daypilot-navigator>
      </div>
      <div class="content">
        <div class="buttons">
        <button (click)="viewDay()" [class]="this.configNavigator.selectMode == 'Day' ? 'selected' : ''">Day</button>
        <button (click)="viewWeek()" [class]="this.configNavigator.selectMode == 'Week' ? 'selected' : ''">Week</button>
        <button (click)="viewMonth()" [class]="this.configNavigator.selectMode == 'Month' ? 'selected' : ''">Month</button>
        </div>

        <daypilot-calendar [config]="configDay" [events]="events" #day></daypilot-calendar>
        <daypilot-calendar [config]="configWeek" [events]="events" #week></daypilot-calendar>
        <daypilot-month [config]="configMonth" [events]="events" #month></daypilot-month>
      </div>
    </div>

  `,
  styles: [`
    .container {
      display: flex;
      flex-direction: row;
    }

    .navigator {
      width: 190px;
    }

    .content {
      flex-grow: 1;
    }
    
    .buttons {
      margin-bottom: 10px;
    }

    button {
      background-color: #3c78d8;
      color: white;
      border: 0;
      padding: .5rem 1rem;
      width: 80px;
      font-size: 14px;
      cursor: pointer;
      margin-right: 5px;
    }
    
    button.selected {
      background-color: #1c4587;
    }

  `]
})
export class CalendarComponent implements AfterViewInit {

  @ViewChild("day") day: DayPilotCalendarComponent;
  @ViewChild("week") week: DayPilotCalendarComponent;
  @ViewChild("month") month: DayPilotMonthComponent;
  @ViewChild("navigator") nav: DayPilotNavigatorComponent;

  events: any[] = [];

  date = DayPilot.Date.today();

  configNavigator: any = {
    showMonths: 3,
    cellWidth: 25,
    cellHeight: 25,
    onVisibleRangeChanged: args => {
      this.loadEvents();
    }
  };

  selectTomorrow() {
    this.date = DayPilot.Date.today().addDays(1);
  }

  changeDate(date: DayPilot.Date): void {
    this.configDay.startDate = date;
    this.configWeek.startDate = date;
    this.configMonth.startDate = date;
  }

  configDay: any = {
  };

  configWeek: any = {
    viewType: "Week",
    onTimeRangeSelected: function (args) {
      DayPilot.Modal.prompt("Create a new event:", "Event 1").then(function(modal) {
        var dp = args.control;
        dp.clearSelection();
        if (!modal.result) { return; }
        dp.events.add(new DayPilot.Event({
          start: args.start,
          end: args.end,
          id: DayPilot.guid(),
          text: modal.result
        }));
      });
    }
  };

  configMonth: any = {

  };

  constructor(private ds: DataService) {
    this.viewWeek();
  }

  ngAfterViewInit(): void {
    this.loadEvents();
  }

  loadEvents(): void {
    let from = this.nav.control.visibleStart();
    let to = this.nav.control.visibleEnd();
    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });
  }

  viewDay():void {
    this.configNavigator.selectMode = "Day";
    this.configDay.visible = true;
    this.configWeek.visible = false;
    this.configMonth.visible = false;
  }

  viewWeek():void {
    this.configNavigator.selectMode = "Week";
    this.configDay.visible = false;
    this.configWeek.visible = true;
    this.configMonth.visible = false;
  }

  viewMonth():void {
    this.configNavigator.selectMode = "Month";
    this.configDay.visible = false;
    this.configWeek.visible = false;
    this.configMonth.visible = true;
  }


}