Angular Material Datepicker [Step-by-Step Guide]

Angular Datepicker is a built-in material component that allows us to enter the date through text input or by choosing the date from a calendar. It allows users to enter the date through text input or by choosing the date from the calendar. It comprises several components and directives that work together.

Here is the step-by-step guide:

Step 1: Install the Angular CLI

npm install -g @angular/cli 

Create the Angular project using the following command.

ng new datepicker

Step 2: Install other libraries

Go into the project and install the hammerjs using the following command.

npm install --save hammerjs

Hammer.js is the optional dependency and helps with touch support for a few components.

Install Angular Material and Angular Animations using the following command.

npm install --save @angular/material @angular/animations @angular/cdk

Include hammerjs inside the angular.json file. You can find this file at the root of the project.

Step 3: Import a pre-built theme and Material icons

Angular Material comes with some pre-built themes. These themes have set off the colors and basic styling.

The main available themes are indigo-pinkdeeppurple-amberpurple-green, and pink-bluegrey.

To import the theme, you can add the following code to your global styles.css file. The file is inside the src folder.

@import '~@angular/material/prebuilt-themes/indigo-pink.css';

You can also access the Material Design icons and use named icons with a <mat-icon> component.

To import them to your project, we can add this to the head section of your project’s root index.html file.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Datepicker</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>
<body>
  <app-root></app-root>
</body>
</html>

Step 4: Create a custom material module file

Inside the src >> app folder, create one file called material.module.ts and add the following code.

// material.module.ts

import { NgModule } from '@angular/core';
import { MatDatepickerModule } from '@angular/material';

@NgModule({
  imports: [
    MatDatepickerModule
  ],
  exports: [
    MatDatepickerModule
  ]
})

export class MaterialModule {}

This file is written on its own because it is easy to include all the Material components in this file, which will then be imported inside the app.module.ts.

// material.module.ts

import { NgModule } from '@angular/core';
import { MatDatepickerModule,
        MatNativeDateModule,
        MatFormFieldModule,
        MatInputModule } from '@angular/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports: [
    MatDatepickerModule,
    MatFormFieldModule,
    MatNativeDateModule,
    MatInputModule,
    BrowserAnimationsModule
  ],
  exports: [
    MatDatepickerModule,
    MatFormFieldModule,
    MatNativeDateModule,
    MatInputModule,
    BrowserAnimationsModule
  ],
  providers: [ MatDatepickerModule ],
})

export class MaterialModule {}

Step 5: Import MaterialModule in an app.module.ts file.

Import MaterialModule inside the app.module.ts file.

// app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { MaterialModule } from './material.module';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    MaterialModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Write the Datepicker HTML code inside the app.component.html file.

<!-- app.component.html -->

<mat-form-field>
  <input matInput [matDatepicker]="picker" placeholder="Choose a date">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

Save the file, go to a terminal or cmd, and start Angular Development Server.

ng serve --open

Starting the angular development server

Go to the browser, and see something like the below image.

Screenshot of angular datepicker interfaceStep 6: Connecting a datepicker to an input

A datepicker comprises text input and a calendar popup connected via the matDatePicker property on the text input.

<input [matDatepicker]="myDatepicker">
<mat-datepicker #myDatepicker></mat-datepicker>

There is an optional datepicker toggle button available. The toggle button can be added to the example above:

<input [matDatepicker]="myDatepicker">
<mat-datepicker-toggle [for]="myDatepicker"></mat-datepicker-toggle>
<mat-datepicker #myDatepicker></mat-datepicker>

It works the same with an input that is part of a <mat-form-field>, and a toggle button can easily be used as a prefix or suffix on the material input:

<mat-form-field>
  <input matInput [matDatepicker]="myDatepicker">
  <mat-datepicker-toggle matSuffix [for]="myDatepicker"></mat-datepicker-toggle>
  <mat-datepicker #myDatepicker></mat-datepicker>
</mat-form-field>

Step 7: Setting the calendar starting view

The startView property of <mat-datepicker> could be used to set the look that will show up when the calendar first opens. It can be configured to monthyear, or multi-year; by default, it will begin to month view.

A month, year, or range of years that a calendar opens to is determined by first checking if any date is currently selected and if so, it will open to a month or year containing that date. Otherwise, it will open in a month or year, providing today’s date.

This behavior can be easily overridden using the startAt property of <mat-datepicker>. In this case, a calendar will open to the month or year containing the startAt date.

<mat-form-field>
  <input matInput [matDatepicker]="picker" placeholder="Choose a date">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker startView="year" [startAt]="startDate"></mat-datepicker>
</mat-form-field>

Screenshot of choosing the date

You can find the code on Github.

GITHUB CODE

Angular Datepicker Validation

Three properties add the date validation to the datepicker input.

The first two are the min and max properties.

To enforce validation on input, these properties will turn off all the dates on the calendar popup before or after the respective values and prevent the user from advancing the calendar past the month or year (depending on the current view) containing the min or max date.

See the following HTML markup.

<mat-form-field class="example-full-width">
  <input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="picker" placeholder="Choose a date">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

 Also, see the typescript file related to the above markup.

import {Component} from '@angular/core';

/** @title Datepicker with min & max validation */
@Component({
  selector: 'datepicker-min-max-example',
  templateUrl: 'datepicker-min-max-example.html',
  styleUrls: ['datepicker-min-max-example.css'],
})
export class DatepickerMinMaxExample {
  minDate = new Date(2000, 0, 1);
  maxDate = new Date(2020, 0, 1);
}

The second way to add the date validation is by using the matDatepickerFilter property of the datepicker input.

This property accepts a function of <D> => boolean (where <D> is the date type used by the datepicker, see Choosing a date implementation).

A true result indicates the date is valid, and a false result suggests it is not.

Again this will also disable the dates on a calendar that are invalid.

However, a critical difference between using matDatepickerFilter vs. using min or max is that filtering out all dates before or after a certain point will not prevent a user from advancing a calendar past that point.

<mat-form-field class="example-full-width">
  <input matInput [matDatepickerFilter]="myFilter" [matDatepicker]="picker" placeholder="Choose a date">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

See the Typescript file related to the above markup.

import {Component} from '@angular/core';

/** @title Datepicker with filter validation */
@Component({
  selector: 'datepicker-filter-example',
  templateUrl: 'datepicker-filter-example.html',
  styleUrls: ['datepicker-filter-example.css'],
})
export class DatepickerFilterExample {
  myFilter = (d: Date): boolean => {
    const day = d.getDay();
    // Prevent Saturday and Sunday from being selected.
    return day !== 0 && day !== 6;
  }
}

In this example, the user can go back past 2005, but all the dates before then will be unselectable. They will not be able to go further back in the calendar than 2000.

The input will have validation errors if they manually type in a date before the min, after the max, or filtered out.

Each validation property has a different error that can be checked:

  1. For example, the value that violates a min property will have the matDatepickerMin error.
  2. The value that violates a max property will have the matDatepickerMax error.
  3. The value that violates a matDatepickerFilter property will have the matDatepickerFilter error.

The input’s native (input) and (change) events will only trigger user interaction with the input element; they will not fire when the user selects the date from the calendar popup.

Therefore, a datepicker input also supports (dateInput) and (dateChange) events — this trigger when a user interacts with either an input or the popup.

The (dateInput) event will fire whenever the value changes due to the user typing or selecting a date from the calendar. Likewise, the (dateChange) event will fire whenever the user finishes typing input (on <input> blur) or when a user chooses the date from a calendar.

<mat-form-field>
  <input matInput [matDatepicker]="picker" placeholder="Input & change events"
         (dateInput)="addEvent('input', $event)" (dateChange)="addEvent('change', $event)">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

<div class="example-events">
  <div *ngFor="let e of events">{{e}}</div>
</div>

See the typescript file related to that markup.

import {Component} from '@angular/core';
import {MatDatepickerInputEvent} from '@angular/material/datepicker';

/** @title Datepicker input and change events */
@Component({
  selector: 'datepicker-events-example',
  templateUrl: 'datepicker-events-example.html',
  styleUrls: ['datepicker-events-example.css'],
})
export class DatepickerEventsExample {
  events: string[] = [];

  addEvent(type: string, event: MatDatepickerInputEvent) {
    this.events.push(`${type}: ${event.value}`);
  }
}

As with any standard <input>, it is possible to disable the datepicker input by adding the disabled property.

By default, the <mat-datepicker> and <mat-datepicker-toggle> will inherit their disabled state from the <input>, but this can be overridden by setting a disabled property on the datepicker or toggle elements.

This is very useful if you want to disable the text input but allow selection via the calendar or vice-versa.

See the following HTML Markup.

<p>
  <mat-form-field>
    <input matInput [matDatepicker]="dp1" placeholder="Completely disabled" disabled>
    <mat-datepicker-toggle matSuffix [for]="dp1"></mat-datepicker-toggle>
    <mat-datepicker #dp1></mat-datepicker>
  </mat-form-field>
</p>

<p>
  <mat-form-field>
    <input matInput [matDatepicker]="dp2" placeholder="Popup disabled">
    <mat-datepicker-toggle matSuffix [for]="dp2" disabled></mat-datepicker-toggle>
    <mat-datepicker #dp2></mat-datepicker>
  </mat-form-field>
</p>

<p>
  <mat-form-field>
    <input matInput [matDatepicker]="dp3" placeholder="Input disabled" disabled>
    <mat-datepicker-toggle matSuffix [for]="dp3"></mat-datepicker-toggle>
    <mat-datepicker #dp3 disabled="false"></mat-datepicker>
  </mat-form-field>
</p>

See the TypeScript file.

import {Component} from '@angular/core';

/** @title Disabled datepicker */
@Component({
  selector: 'datepicker-disabled-example',
  templateUrl: 'datepicker-disabled-example.html',
  styleUrls: ['datepicker-disabled-example.css'],
})
export class DatepickerDisabledExample {}

That’s it!

4 thoughts on “Angular Material Datepicker [Step-by-Step Guide]”

  1. What is it with Angular?

    “How do I add a date picker?”, something that in Dot Net involves a single line of code with the behaviour and variables related to that object created automatically, but every tutorial I have seen on every control in Angular so far starts with instructions on how to create a project from scratch but here in order to implement it I need to create a material module to determine what it looks like?

    Why does adding a single control seem to involve 10-20 lines of code no matter what one does?

    Bare bones….minimum coding…just a date time picker…nothing else.

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.