I\'m working on an Angular App with Material Design, and I\'m using Moment.js to parse and format dates.
In one of my p
OK, so I finally find a way to change the mat-date-picker
format during run-time (the documentation didn't help at all).
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.service
import { 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
}
}
// customDateAdapter.ts
import { 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
.
// app.module.ts
import { 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);
}