Contents

Hi! In this article, I’d like to show you how to create datepickers with many custom date formats in Angular Material.

Hi! Recently I wanted to create datepicker with year month format and another datepicker with date format. Unfortunately there was no such an example in the official Angular Material documentation. That’s why I decided to share my knowledge with you 🙂

To use datepicker component from Angular Material we have to install the following dependencies:

ng add @angular/material
npm i @angular/material-moment-adapter
npm i moment

After installation we can create app module:

import { YearMonthFormatDirective } from './directives/year-month-format.directive';
import { DateFormatDirective } from './directives/date-format.directive';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { ReactiveFormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatMomentDateModule } from '@angular/material-moment-adapter';

@NgModule({
  declarations: [
    AppComponent,
    DateFormatDirective,
    YearMonthFormatDirective
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    ReactiveFormsModule,
    MatDatepickerModule,
    MatInputModule,
    MatMomentDateModule
  ],
  providers: [
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Thanks to importing MatMomentDateModule, we have one global date format by default.

To use custom date format we have to create and provide our format in this way:

import { YearMonthFormatDirective } from './directives/year-month-format.directive';
import { DateFormatDirective } from './directives/date-format.directive';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { ReactiveFormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatMomentDateModule } from '@angular/material-moment-adapter';
import { MAT_DATE_FORMATS } from '@angular/material/core';
export const FORMAT = {
  parse: {
      dateInput: 'DD-MM-YYYY',
  },
  display: {
      dateInput: 'DD-MM-YYYY',
      monthYearLabel: 'MMM YYYY',
      dateA11yLabel: 'LL',
      monthYearA11yLabel: 'MMMM YYYY',
  },
};
@NgModule({
  declarations: [
    AppComponent,
    DateFormatDirective,
    YearMonthFormatDirective
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    ReactiveFormsModule,
    MatDatepickerModule,
    MatInputModule,
    MatMomentDateModule
  ],
  providers: [
    { provide: MAT_DATE_FORMATS, useValue: FORMAT }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Custom date format is provided with MAT_DATE_FORMATS injection token.

Finally to create many custom date formats we can create custom directives. These directives can be applied to datepickers that we want to format in the directive specific way. So let’s do that:

import { MAT_DATE_FORMATS } from '@angular/material/core';
import { Directive } from '@angular/core';
export const FORMAT = {
    parse: {
        dateInput: 'DD/MM/YYYY',
    },
    display: {
        dateInput: 'DD/MM/YYYY',
        monthYearLabel: 'MMM YYYY',
        dateA11yLabel: 'LL',
        monthYearA11yLabel: 'MMMM YYYY',
    },
};
@Directive({
    selector: '[appDateFormat]',
    providers: [
        { provide: MAT_DATE_FORMATS, useValue: FORMAT },
    ],
})
export class DateFormatDirective {
}
import { MAT_DATE_FORMATS } from '@angular/material/core';
import { Directive } from '@angular/core';
export const FORMAT = {
    parse: {
        dateInput: 'MM/YYYY',
    },
    display: {
        dateInput: 'MM/YYYY',
        monthYearLabel: 'MMM YYYY',
        dateA11yLabel: 'LL',
        monthYearA11yLabel: 'MMMM YYYY',
    },
};
@Directive({
    selector: '[appYearMonthFormat]',
    providers: [
        { provide: MAT_DATE_FORMATS, useValue: FORMAT },
    ],
})
export class YearMonthFormatDirective {
}
<form [formGroup]="form">
  <mat-form-field appYearMonthFormat>
    <mat-label>Month and Year</mat-label>
    <input matInput [matDatepicker]="dp1" formControlName="yearMonth">
    <mat-datepicker-toggle matSuffix [for]="dp1"></mat-datepicker-toggle>
    <mat-datepicker #dp1 startView="multi-year" (yearSelected)="chosenYearHandler($event)"
      (monthSelected)="chosenMonthHandler($event, dp1)">
    </mat-datepicker>
  </mat-form-field>
  <mat-form-field appDateFormat>
    <mat-label>Date</mat-label>
    <input matInput [matDatepicker]="dp2" formControlName="date">
    <mat-datepicker-toggle matSuffix [for]="dp2"></mat-datepicker-toggle>
    <mat-datepicker #dp2 startView="multi-year"></mat-datepicker>
  </mat-form-field>
  <mat-form-field>
    <mat-label>Default date</mat-label>
    <input matInput [matDatepicker]="dp3" formControlName="defaultDate">
    <mat-datepicker-toggle matSuffix [for]="dp3"></mat-datepicker-toggle>
    <mat-datepicker #dp3 startView="multi-year"></mat-datepicker>
  </mat-form-field>
</form>
import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { Moment } from 'moment';
import * as moment from 'moment';
import { MatDatepicker } from '@angular/material/datepicker';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private fb: FormBuilder) { }
  title = 'angular-material-datepicker-with-many-date-formats';
  form = this.fb.group({
    yearMonth: [moment()],
    date: [moment()],
    defaultDate: [moment()]
  });
  chosenYearHandler(normalizedYear: Moment) {
    const ctrlValue = this.form.controls.yearMonth.value;
    ctrlValue.year(normalizedYear.year());
    this.form.controls.yearMonth.setValue(ctrlValue);
  }
  chosenMonthHandler(normalizedMonth: Moment, datepicker: MatDatepicker<Moment>) {
    const ctrlValue = this.form.controls.yearMonth.value;
    ctrlValue.month(normalizedMonth.month());
    this.form.controls.yearMonth.setValue(ctrlValue);
    datepicker.close();
  }
}

We can use directive if we want one of our custom formats to be applied. In the third field we hadn’t used any directive so the default format has been applied. You can play with this code on StackBlitz.

In this article we went through usage of many Angular Material datepicker formats. To use many custom formats we can create directives that provide new format overriding the default one. Hope you enjoyed!