Angular Material Datepicker Validation
July 20, 2020
This page will walk through Angular Material Datepicker validation example. Datepicker can be validated in following ways.
1. Validate
required
using Validators.required
in FormControl
.
2. For minimum and maximum date selection, use
min
and max
property of Datepicker input text.
3. We can use
matDatepickerFilter
to validate Datepicker conditionally.
4. We can create custom validator to validate Datepicker.
5. For Datepicker range selection, use
matStartDateInvalid
and matEndDateInvalid
error.
On this page we will provide complete demo to validate Datepicker step-by-step.
Contents
Technologies Used
Find the technologies being used in our example.1. Angular 10.0.0
2. Angular Material 10.0.0
3. Node.js 12.5.0
4. NPM 6.9.0
5. moment.js 2.27.0
Required
Validation
For required
validation, configure Validators.required
in form control.
studentForm = this.formBuilder.group({ dateOfBirth: ['', Validators.required], ------ });
<mat-error>
. The error message will be displayed if required
validation fails.
<mat-form-field> <mat-label>Date of Birth</mat-label> <input matInput [matDatepicker]="dob" formControlName="dateOfBirth"> <mat-datepicker-toggle matSuffix [for]="dob"></mat-datepicker-toggle> <mat-datepicker #dob></mat-datepicker> <mat-error *ngIf="studentForm.get('dateOfBirth').hasError('required')"> Valid date required. </mat-error> </mat-form-field>
min
and max
Validation
To validate minimum and maximum date entered by user manually or selected from calendar, can be validated using min
and max
property. It is used in Datepicker as following.
<mat-form-field> <input matInput [matDatepicker]="seStDt" [min]="minDate" [max]="maxDate" formControlName="sessionStDate"> ------ </mat-form-field>
min
and max
properties,
a. The calendar will disable past and future dates and user cannot select date lesser than configured minimum date as well as date greater than configured maximum date.
b. If user manually enters out of the date range in input text, the Datepicker value will be invalid. We can display error messages by checking
matDatepickerMin
and matDatepickerMax
error properties.
Suppose we have a
FormGroup
with following form control.
studentForm = this.formBuilder.group({ sessionStDate: ['', Validators.required], ------ });
minDate: Moment; maxDate: Moment; ngOnInit() { const currentYear = moment().year(); this.minDate = moment([currentYear -1, 0, 1]); this.maxDate = moment([currentYear + 1, 11, 31]) }
min
and max
validation with error messages.
<mat-form-field> <mat-label>Session start date</mat-label> <input matInput [matDatepicker]="seStDt" [min]="minDate" [max]="maxDate" formControlName="sessionStDate"> <mat-datepicker-toggle matSuffix [for]="seStDt"></mat-datepicker-toggle> <mat-datepicker #seStDt></mat-datepicker> <mat-error *ngIf="studentForm.get('sessionStDate').hasError('required')"> Session start date required. </mat-error> <mat-error *ngIf="studentForm.get('sessionStDate').hasError('matDatepickerMin')"> Invalid minimum date. </mat-error> <mat-error *ngIf="studentForm.get('sessionStDate').hasError('matDatepickerMax')"> Invalid maximum date. </mat-error> </mat-form-field>
Validation with matDatepickerFilter
Datepicker can be validated using matDatepickerFilter
property of Datepicker input. The matDatepickerFilter
accepts a function that returns Boolean. For true
value date is valid and for false
value date is invalid. The calendar will disable invalid dates and cannot be selected. But for manual entry of invalid date, we can display error message using its matDatepickerFilter
error.
Find a function to be assigned to
matDatepickerFilter
property that will disable weekends.
myDateFilter = (m: Moment | null): boolean => { const day = (m || moment()).day(); return day !== 0 && day !== 6; }
matDatepickerFilter
property and matDatepickerFilter
error.
<mat-form-field> <mat-label>Session close date</mat-label> <input matInput [matDatepicker]="seClDt" [matDatepickerFilter]="myDateFilter" formControlName="sessionClDate"> <mat-datepicker-toggle matSuffix [for]="seClDt"></mat-datepicker-toggle> <mat-datepicker #seClDt></mat-datepicker> <mat-error *ngIf="studentForm.get('sessionClDate').hasError('matDatepickerFilter')"> Weekends not allowed. </mat-error> </mat-form-field>
Using Custom Validator
We can create our own validator to validate Datepicker. Find a custom validator that createsinvalidDOBYear
error.
datepicker-validator.ts
import { ValidatorFn, AbstractControl } from '@angular/forms'; import { Moment } from 'moment'; export function datePickerValidator(): ValidatorFn { return (control: AbstractControl): { [key: string]: any } | null => { let forbidden = true; if (control.value) { const moment: Moment = control.value; if (moment.year() > 2000 ) { forbidden = false; } } return forbidden ? { 'invalidDOBYear': true } : null; }; }
Moment
because our demo application will import MomentDateModule
which is based on moment.js
. If our application imports MatNativeDateModule
then we should use native JavaScript Date
.
Now find the
FormGroup
which uses our custom validation.
studentForm = this.formBuilder.group({ dateOfBirth: ['', [Validators.required, datePickerValidator()]], ------ });
invalidDOBYear
to display error message.
<mat-form-field appearance="fill"> ------ <mat-error *ngIf="studentForm.get('dateOfBirth').hasError('invalidDOBYear')"> Select year greater than 2000. </mat-error> </mat-form-field>
Date Range Validation
Date range can be validated in Datepicker range selection. The Datepicker for date range selection is created using<mat-date-range-picker>
and <mat-date-range-input>
. From Datepicker calendar, we cannot select start date greater than end date but user can enter invalid dates manually in input text. To display error messages in this case, we need to use matStartDateInvalid
and matEndDateInvalid
error.
Suppose we have a
FormGroup
.
studentForm = this.formBuilder.group({ ------ admDateRange: this.formBuilder.group({ startDate: '', endDate: '' }) });
matStartDateInvalid
and matEndDateInvalid
error.
<mat-form-field> <mat-label>Admission Date Range</mat-label> <mat-date-range-input [rangePicker]="admDateRangePicker" formGroupName="admDateRange"> <input matStartDate formControlName="startDate" placeholder="Start date"> <input matEndDate formControlName="endDate" placeholder="End date"> </mat-date-range-input> <mat-datepicker-toggle matSuffix [for]="admDateRangePicker"></mat-datepicker-toggle> <mat-date-range-picker #admDateRangePicker></mat-date-range-picker> <mat-error *ngIf="studentForm.get('admDateRange').get('startDate').hasError('matStartDateInvalid')"> Invalid start date. </mat-error> <mat-error *ngIf="studentForm.get('admDateRange').get('endDate').hasError('matEndDateInvalid')"> Invalid end date. </mat-error> <mat-error *ngIf="studentForm.get('admDateRange').get('startDate').invalid || studentForm.get('admDateRange').get('endDate').invalid"> Valid date required. </mat-error> </mat-form-field>
Complete Example
Find the complete demo application usingmoment.js
.
student.component.html
<h3>Datepicker Validation</h3> For manual date entry, use date format (DD-MM-YYYY). <br/><br/> <form [formGroup]="studentForm" (ngSubmit)="onFormSubmit()"> <mat-form-field> <mat-label>Student Name</mat-label> <input matInput formControlName="name"> <mat-error *ngIf="studentForm.get('name').hasError('required')"> Student name required. </mat-error> </mat-form-field> <br/><br/> <mat-form-field appearance="fill"> <mat-label>Date of Birth</mat-label> <input matInput [matDatepicker]="dob" formControlName="dateOfBirth"> <mat-datepicker-toggle matSuffix [for]="dob"></mat-datepicker-toggle> <mat-datepicker #dob></mat-datepicker> <mat-error *ngIf="studentForm.get('dateOfBirth').hasError('required')"> Valid date required. </mat-error> <mat-error *ngIf="studentForm.get('dateOfBirth').hasError('invalidDOBYear')"> Select year greater than 2000. </mat-error> </mat-form-field> <br/><br/> <mat-form-field appearance="fill"> <mat-label>Session start date</mat-label> <input matInput [matDatepicker]="seStDt" [min]="minDate" [max]="maxDate" formControlName="sessionStDate"> <mat-datepicker-toggle matSuffix [for]="seStDt"></mat-datepicker-toggle> <mat-datepicker #seStDt></mat-datepicker> <mat-error *ngIf="studentForm.get('sessionStDate').hasError('required')"> Valid date required. </mat-error> <mat-error *ngIf="studentForm.get('sessionStDate').hasError('matDatepickerMin')"> Invalid minimum date. </mat-error> <mat-error *ngIf="studentForm.get('sessionStDate').hasError('matDatepickerMax')"> Invalid maximum date. </mat-error> </mat-form-field> <br/><br/> <mat-form-field appearance="fill"> <mat-label>Session close date</mat-label> <input matInput [matDatepicker]="seClDt" [matDatepickerFilter]="myDateFilter" formControlName="sessionClDate"> <mat-datepicker-toggle matSuffix [for]="seClDt"></mat-datepicker-toggle> <mat-datepicker #seClDt></mat-datepicker> <mat-error *ngIf="studentForm.get('sessionClDate').hasError('required')"> Valid date required. </mat-error> <mat-error *ngIf="studentForm.get('sessionClDate').hasError('matDatepickerFilter')"> Weekends not allowed. </mat-error> </mat-form-field> <br/><br/> <mat-form-field appearance="fill"> <mat-label>Admission Date Range</mat-label> <mat-date-range-input [rangePicker]="admDateRangePicker" formGroupName="admDateRange"> <input matStartDate formControlName="startDate" placeholder="Start date"> <input matEndDate formControlName="endDate" placeholder="End date"> </mat-date-range-input> <mat-datepicker-toggle matSuffix [for]="admDateRangePicker"></mat-datepicker-toggle> <mat-date-range-picker #admDateRangePicker></mat-date-range-picker> <mat-error *ngIf="studentForm.get('admDateRange').get('startDate').hasError('matStartDateInvalid')"> Invalid start date. </mat-error> <mat-error *ngIf="studentForm.get('admDateRange').get('endDate').hasError('matEndDateInvalid')"> Invalid end date. </mat-error> <mat-error *ngIf="studentForm.get('admDateRange').get('startDate').invalid || studentForm.get('admDateRange').get('endDate').invalid"> Valid date required. </mat-error> </mat-form-field> <br/><br/><br/> <button mat-raised-button>Submit</button> </form>
import { Component, OnInit } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; import { StudentService } from './student.service'; import { datePickerValidator } from './datepicker-validator'; import * as _moment from 'moment'; import { Moment } from 'moment'; const moment = _moment; @Component({ selector: 'app-student', templateUrl: './student.component.html' }) export class StudentComponent implements OnInit { minDate: Moment; maxDate: Moment; myDateFilter = (m: Moment | null): boolean => { const day = (m || moment()).day(); return day !== 0 && day !== 6; } constructor(private formBuilder: FormBuilder, private studentService: StudentService) { } ngOnInit() { const currentYear = moment().year(); this.minDate = moment([currentYear -1, 0, 1]); this.maxDate = moment([currentYear + 1, 11, 31]) } studentForm = this.formBuilder.group({ name: ['', Validators.required], dateOfBirth: ['', [Validators.required, datePickerValidator()]], sessionStDate: ['', Validators.required], sessionClDate: ['', Validators.required], admDateRange: this.formBuilder.group({ startDate: '', endDate: '' }) }); onFormSubmit() { this.studentService.saveStudent(this.studentForm.value); this.studentForm.reset(); } }
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class StudentService { saveStudent(student) { console.log(JSON.stringify(student)); } }
export const MY_DATE_FORMATS = { parse: { dateInput: 'DD-MM-YYYY', }, display: { dateInput: 'DD-MM-YYYY', monthYearLabel: 'MMM YYYY', dateA11yLabel: 'LL', monthYearA11yLabel: 'MMMM YYYY' }, };
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-student></app-student> ` }) export class AppComponent { }
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MatInputModule } from '@angular/material/input'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MomentDateModule } from '@angular/material-moment-adapter'; import { MAT_DATE_FORMATS } from '@angular/material/core'; import { AppComponent } from './app.component'; import { StudentComponent } from './student.component'; import { MY_DATE_FORMATS } from './my-date-formats'; @NgModule({ declarations: [ AppComponent, StudentComponent ], imports: [ BrowserModule, FormsModule, ReactiveFormsModule, BrowserAnimationsModule, MatInputModule, MatDatepickerModule, MomentDateModule ], providers: [ { provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMATS } ], bootstrap: [ AppComponent ] }) export class AppModule { }
Run Application
To run the application, find the steps.1. Install Angular CLI using link.
2. Install Angular Material using link.
3. Install
moment.js
.
npm install moment --save
5. Use downloaded src in your Angular CLI application.
6. Run ng serve using command prompt.
7. Access the URL http://localhost:4200
Find the print screen of the output.

References
DatepickerMoment.js Documentation