Angular Material Calendar Component

Angular Material Calendar Component

As of version Angular 7.1, there is still no mention of the calendar component in the official Angular Material docs. The form controls include a datepicker component, which internally uses a calendar popup for date entry. However, if you want to display a calendar that is always open, the date picker is not feasible. In this post, I will talk about the calendar component that is available as part of the Angular Material library. I will also show how to use it to get date input from the user through events.

Datepicker Component

Angular Material docs demonstrate a lot of the date picker functionality. mat-datepicker control is an input that can accept date input in a couple of ways:

  • Manual date value entry in the input
  • Ability to pick a date value using the calendar popup (user must click input to popup the calendar)

Calendar Component

While the date picker control is a very useful form component, it is not always the best way to get date value from the user. I was faced with a requirement where I had to display a calendar that is always open. The user would click on a date and update certain values in the UI change corresponding to the value selected.

Having went through the list of components, I could not find anything about a stand-alone calendar. I continued to dig deeper into the date picker.. and figured out that the MatDatePickerModule brings along a component called mat-calendar, which is what’s shown in the popup of the date picker.

With that said, mat-calendar component is fully-functional with date, month & year selection. This is what it looks like:

Calendar Component in Angular App
Calendar Component in Angular App

Just so you know, the full source code is available on GitHub. Alternatively, run the live demo below.

How to Use the Calendar Component in Angular

First of all, setup your angular project and import angular material library. Once ready, follow the steps below:

Install Moment.js and Material Moment Adapter from npm:

npm install moment --save
npm install @angular/material-moment-adapter --save

I prefer using Moment.js for date manipulation because it is very lightweight and offers advanced features. If you don’t want to use moment, read more about Angular’s native date implementation here.

Next, import the MatDatePickerModule and MatMomentDateModule components into your app. You can now use the calendar component in any Angular view.

<div class="calendar-wrapper">
    <mat-calendar #calendar [(selected)]="selectedDate"></mat-calendar>
</div>

We can then access this component in the typescript file through the ViewChild property decorator, as shown below:

  @ViewChild('calendar') calendar: MatCalendar<Moment>;
  selectedDate: Moment;

Calendar Events

As there is no documentation for this component, I had to figure things out myself. It appears that the calendar component has two events that we can tap into: monthSelected and selectedChange.

monthSelected Event

As the name suggests this event fires when the user changes the currently displayed month.

// app.component.html
<mat-calendar #calendar [(selected)]="selectedDate" (monthSelected)="monthSelected($event)"></mat-calendar>

// app.component.ts
monthSelected(date) {
  alert(`Selected: ${date}`);
}

However, the monthSelected event is unfortunately not fired for the arrow buttons on the top right hand corner. If you need to access these button clicks, I recommend using the Renderer2 service for wiring-up event handlers.

My advice is to create a custom wrapper component to improve separation of concerns.

  ngAfterViewInit() {
    // Find all arrow buttons in the calendar
    let buttons = document.querySelectorAll('mat-calendar mat-calendar-header button');

    if (buttons) {
      // Listen for click event
      Array.from(buttons).forEach(button => {
        this.renderer.listen(button, "click", () => {
          console.log('Arrow button clicked');
        });
      })
    }
  }

selectedChange Event

This event fires when there is a change in date selection. Newly selected date is passed into the event handler as an argument.

// app.component.html
<mat-calendar #calendar [(selected)]="selectedDate" (selectedChange)="onDateChanged($event)"></mat-calendar>

// app.component.ts
onDateChanged(date) {
  alert(`Selected: ${date}`);
}

Summary

In this post, we got our hands dirty with the calendar component of Angular Material library. I have been using this in a real-world application for quite some time and haven’t had any issues yet. While the component is very helpful, I am not sure why the documentation does not mention it. If you know the answer, drop a comment below!

The full source code is available on GitHub.

Umut Esen

Umut is an enthusiastic software developer, latest web and mobile technology adapter and primary author of onthecode.

This Post Has 4 Comments

  1. A great article! Thank you!

  2. Great article Umut. Thanks for sharing. Any idea how to set min / max selection date and disable calendar?

    1. Umut Esen

      I would consider creating a wrapper component, which would be used as a generic calendar. This wrapper component would accept min/max date values through input parameters. All you would have to do then is to perform min/max validation inside onDateChanged event.

  3. It’s very helpful @Umut Esen … I couldn’t find a way to show multi-month view. Can you please let me know the solution for that.

Leave a Reply

Close Menu