Features

  • Angular Calendar component that displays events/appointments
  • Angular Date Picker component (Navigator) that allows changing the visible date
  • Next/Previous/Today buttons for quick date changing
  • Includes a trial version of DayPilot Pro for JavaScript (see 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.

Calendar Configurator

This Angular project was generated using Calendar UI Builder - an online calendar component configuration application.

Angular Calendar Component

angular-calendar-date-switching-tutorial-calendar-component.png

In the first step, we will add the calendar component to our Angular application.

The <daypilot-calendar> tag uses [config] attribute to load the configuration and [events] attribute to load event data.

HTML

<daypilot-calendar [config]="config" [events]="events" #calendar></daypilot-calendar>

TypeScript

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

@Component({
  selector: 'calendar-component',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.css']
})
export class CalendarComponent implements AfterViewInit {

  events: any[] = [];

  config: any = {
    startDate: new DayPilot.Date("2018-06-01"),
    viewType: "Week",
    cellHeight: 30,
    headerHeight: 30,
    hourWidth: 60
  };

  constructor(private ds: DataService) {
  }

  ngAfterViewInit(): void {
    var from = this.calendar.control.visibleStart();
    var to = this.calendar.control.visibleEnd();
    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });
  }

}

Angular Date Picker Component

angular-calendar-date-switching-tutorial-date-picker.png

Now we will add a date picker next to the calendar using DayPilot Navigator component.

<daypilot-navigator [config]="navigatorConfig"></daypilot-navigator>

The [config] attribute points to an object with navigator configuration. We will use the config to set the select mode to week and to customize the appearance:

navigatorConfig: any = {
  showMonths: 3,
  skipMonths: 3,
  selectMode: "week",
  cellWidth: 30,
  cellHeight: 30,
  dayHeaderHeight: 30,
  titleHeight: 30
};

The navigator component allows setting the selected date using date property. It also uses dateChange event for notification of selection changes. We will use the "banana in a box" Angular attribute syntax to set up a two-way binding between the date selected in the navigator component and the startDate property of the calendar component.

<daypilot-navigator [config]="navigatorConfig" [(date)]="config.startDate" #navigator></daypilot-navigator>

Any change of the selected date will automatically update the calendar component. When the week displayed by the calendar changes, we need to load the event data for the new week. The calendar component provides viewChange event which is fired whenever the calendar is updated. We will use this event to detect view changes and load the appointments.

<daypilot-calendar [config]="config" [events]="events" #calendar (viewChange)="viewChange()"></daypilot-calendar>

The viewChange() method loads the events using DataService.getEvents(). This is the same code we had in ngAfterViewInit() in the first version of our application:

viewChange(): void {
  var from = this.calendar.control.visibleStart();
  var to = this.calendar.control.visibleEnd();
  this.ds.getEvents(from, to).subscribe(result => {
    this.events = result;
  });
}

This is how our calendar component looks after integrating the date picker:

HTML

<div class="left">
  <daypilot-navigator [config]="navigatorConfig" [(date)]="config.startDate" #navigator></daypilot-navigator>
</div>
<div class="main">
  <daypilot-calendar [config]="config" [events]="events" #calendar (viewChange)="viewChange()"></daypilot-calendar>
</div>

TypeScript

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

@Component({
  selector: 'calendar-component',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.css']
})
export class CalendarComponent implements AfterViewInit {

  @ViewChild("navigator") navigator: DayPilotNavigatorComponent;
  @ViewChild("calendar") calendar: DayPilotCalendarComponent;

  navigatorConfig: any = {
    showMonths: 3,
    skipMonths: 3,
    selectMode: "week",
    cellWidth: 30,
    cellHeight: 30,
    dayHeaderHeight: 30,
    titleHeight: 30
  };

  events: any[] = [];

  config: any = {
    startDate: new DayPilot.Date("2018-06-01"),
    viewType: "Week",
    cellHeight: 30,
    headerHeight: 30,
    hourWidth: 60
  };

  constructor(private ds: DataService) {
  }

  ngAfterViewInit(): void {
  }

  viewChange(): void {
    var from = this.calendar.control.visibleStart();
    var to = this.calendar.control.visibleEnd();
    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });
  }
}

Next/Today/Previous Buttons

angular-calendar-date-switching-tutorial-previous-today-next.png

In the final step, we will add shortcut buttons for quick date changes. These buttons will directly modify config.startDate property. Angular will automatically detect this change and update the calendar. The calendar will fire viewChange event which loads the data using the viewChange() method that we already added.

HTML

<div class="left">
  <daypilot-navigator [config]="navigatorConfig" [(date)]="config.startDate" #navigator></daypilot-navigator>
</div>
<div class="main">
  <div class="buttons">
    <a href="#" (click)="navigatePrevious($event)">Previous</a>
    <a href="#" (click)="navigateToday($event)">Today</a>
    <a href="#" (click)="navigateNext($event)">Next</a>
  </div>
  <daypilot-calendar [config]="config" [events]="events" #calendar (viewChange)="viewChange()"></daypilot-calendar>
</div>

TypeScript

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

@Component({
  selector: 'calendar-component',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.css']
})
export class CalendarComponent implements AfterViewInit {

  // ...

  navigatePrevious(event): void {
    event.preventDefault();
    this.config.startDate = this.config.startDate.addDays(-7);
  }

  navigateNext(event): void {
    event.preventDefault();
    this.config.startDate = this.config.startDate.addDays(7);
  }

  navigateToday(event): void {
    event.preventDefault();
    this.config.startDate = DayPilot.Date.today();
  }

}

Full Source Code

calendar.component.css

:host ::ng-deep .calendar_default_colheader_inner {
  padding: 5px;
}

:host ::ng-deep .calendar_default_rowheader_inner {
  padding: 5px;
}

.left {
  float: left;
  width: 200px;
}

.main {
  margin-left: 220px;
}

.buttons {
  margin-bottom: 10px;
}

.buttons a {
  display: inline-block;
  text-align: center;
  background-color: #3c78d8;
  border: 1px solid #1155cc;
  color: #fff;
  padding: 6px 20px;
  border-radius: 2px;
  cursor: pointer;
  margin-right: 5px;
  width: 80px;
  text-decoration: none;
}

calendar.component.html

<div class="left">
  <daypilot-navigator [config]="navigatorConfig" [(date)]="config.startDate" #navigator></daypilot-navigator>
</div>
<div class="main">
  <div class="buttons">
    <a href="#" (click)="navigatePrevious($event)">Previous</a>
    <a href="#" (click)="navigateToday($event)">Today</a>
    <a href="#" (click)="navigateNext($event)">Next</a>
  </div>
  <daypilot-calendar [config]="config" [events]="events" #calendar (viewChange)="viewChange()"></daypilot-calendar>
</div>

calendar.component.ts

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

@Component({
  selector: 'calendar-component',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.css']
})
export class CalendarComponent implements AfterViewInit {

  @ViewChild("navigator") navigator: DayPilotNavigatorComponent;
  @ViewChild("calendar") calendar: DayPilotCalendarComponent;

  expanded: boolean = true;

  navigatorConfig: any = {
    showMonths: 3,
    skipMonths: 3,
    selectMode: "week",
    cellWidth: 30,
    cellHeight: 30,
    dayHeaderHeight: 30,
    titleHeight: 30
  };

  events: any[] = [];

  config: any = {
    startDate: new DayPilot.Date("2018-06-01"),
    viewType: "Week",
    cellHeight: 30,
    headerHeight: 30,
    hourWidth: 60,
    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
        }));
      });
    }
  };

  constructor(private ds: DataService) {
  }

  ngAfterViewInit(): void {
  }

  viewChange(): void {

    var from = this.calendar.control.visibleStart();
    var to = this.calendar.control.visibleEnd();

    console.log("viewChange(): " + from + " " + to);

    this.ds.getEvents(from, to).subscribe(result => {
      this.events = result;
    });
  }

  navigatePrevious(event): void {
    event.preventDefault();
    this.config.startDate = this.config.startDate.addDays(-7);
  }

  navigateNext(event): void {
    event.preventDefault();
    this.config.startDate = this.config.startDate.addDays(7);
  }

  navigateToday(event): void {
    event.preventDefault();
    this.config.startDate = DayPilot.Date.today();
  }

}