How to change Angular Material Datepicker format in run-time How to change Angular Material Datepicker format in run-time angular angular

How to change Angular Material Datepicker format in run-time


OK, so I finally find a way to change the mat-date-picker format during run-time (the documentation didn't help at all).

Step #1 - Create a service that will provide the formatting.

You probable already have a service like this, if no you should create one, so you could control the date-formatting in one place.

// date-time.serviceimport { Injectable } from '@angular/core';import * as moment from 'moment';@Injectable({ providedIn: 'root' })export class DateTimeService{  public getFormat(): string  {    return "DD-MM-YYYY"; // add you own logic here  }  public getLocale(): string  {    return "he-IL"; // add you own logic here  }  }

Step #2 - Create a CustomDateAdapter, that will be responsible for parsing the date during run-time

// customDateAdapter.tsimport { Injectable } from '@angular/core';import { MomentDateAdapter } from '@angular/material-moment-adapter';import * as moment from 'moment';import { DateTimeService } from './date-time.service';@Injectable()export class CustomDateAdapter extends MomentDateAdapter{  constructor(private _dateTimeService: DateTimeService)  {    super('en-US'); // set default locale  }  public format(date: moment.Moment, displayFormat: string): string  {    const locale = this._dateTimeService.getLocale();    const format = this._dateTimeService.getFormat();    return date.locale(locale).format(format);  }}

Please Notice: That "CustomDateAdapter" is a regular class, and not a component. Although we are injecting a service to this class. To achieve this we need to add the @Injectable() decorator to the "CustomDateAdapter", and make some light changes in the app.module.ts.

Step #3 - Modify the app.module.ts to support custom formating and to allow Dependence Injection to CustomDateAdapter.

// app.module.tsimport { DateAdapter, MatNativeDateModule } from '@angular/material';import { MatMomentDateModule } from '@angular/material-moment-adapter'import { CustomDateAdapter } from './<some-path>/customDateAdapter';@NgModule({  imports:  [    MatNativeDateModule,    MatMomentDateModule  ],  providers:  [    CustomDateAdapter, // so we could inject services to 'CustomDateAdapter'    { provide: DateAdapter, useClass: CustomDateAdapter }, // Parse MatDatePicker Format  ]})export class AppModule { /* ... */ }

P.S
Please notice that the code from the question (from the "demo.component.ts") isn't relevant any more.

Demo at Stackblitz


Thanks for your idea! Just for clarification. You can use non-singleton service for setting custom formatting of datepicker value. Extending your code:

import { Injectable } from '@angular/core';    @Injectable({ providedIn: 'root' })    export class DateTimeService {        private _format = 'DD.MM.YYYY';        set format(value: string) {            this._format = value;        }        public getFormat(): string {            return this._format;        }        public getLocale(): string {            return 'ru-ru';        }    }

If you inject this service like this:

providers: [        { provide: MAT_DATE_LOCALE, useValue: 'ru-ru' },        CustomDateAdapter,        DateTimeService,        { provide: DateAdapter, useClass: CustomDateAdapter, deps: [DateTimeService] }]

you can store any value from your component during component working.

constructor(private dateTimeService: DateTimeService) {    }    ngOnInit() {        this.dateTimeService.format = this.format;    }


update: @Gil Epshtain's solution doesn't work if the user wants to manually input DateTime instead of pick DateTime from DateTime picker (remove read-only attribute on input DateTime).my update on customDateAdapter.ts:

public parse(value: any, parseFormat: string | string[]): moment.Moment | null {if(!value) {  return null}const format = this._dateTimeService.getFormat();return _moment(value, format, false);}