13

I'm working at an Angular9 app that works with dates. It displays and updates several <mat-datepicker> fields.

I am using a custom MAT_DATE_FORMATS and MomentDateAdapter (@angular/material-moment-adapter) from https://www.npmjs.com/package/@angular/material-moment-adapter.

I'm using the following code which works okay:

export const APP_MOMENT_DATE_FORMATS =
{    
  parse: {},
  display: {
    dateInput: 'YYYY/MM/DD/MM',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY'
  }
};

//..
providers: [
  {
     provide: MAT_DATE_FORMATS, useValue: APP_MOMENT_DATE_FORMATS
  },
  {
    provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]
  }
]
// ..

Stackblitz demo: https://stackblitz.com/edit/angular-formatted-datepicker-vdtaqj?file=app%2Fdatepicker-overview-example.ts

Now, I was wondering if I could update the value of the APP_MOMENT_DATE_FORMATS.display.dateInput dynamically - eg: maybe it will be setted from a configuration service via a http request, or maybe I will display a selector in the interface.

example:

export const APP_MOMENT_DATE_FORMATS =
  {  
    // ..  
    display: {
     dateInput: this.appService.dateInputFormat,
     // ..
   }
  };

I know that I could implement a custom date adapter, as described here: Angular 2 Material 2 datepicker date format.

But I was wondering if there is another method to do it, without implementing a new custom date adapter.

Thanks.

2 Answers 2

5

After spending hours looking for solution, I come up the below solution by just simply injecting MAT_DATE_FORMATS and change it dynamically:

const APP_MOMENT_DATE_FORMATS =
{
    parse: {
    dateInput: 'MM/DD/YYYY',
    },
    display: {
    dateInput: 'MM/DD/YYYY',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY'
    }
};

@Component({
...  
providers: [
    {
    provide: MAT_DATE_FORMATS, useValue: APP_MOMENT_DATE_FORMATS
    },
    {
    provide: DateAdapter,
    useClass: MomentDateAdapter,
    deps: [MAT_DATE_LOCALE]
    }
]
})

export class DatePickerComponent implements OnInit, OnDestroy {

constructor(@Inject(MAT_DATE_FORMATS) public data: any) {
    data.parse.dateInput = 'DD/MM/YYYY'
    data.display.dateInput = 'DD/MM/YYYY'
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

how to change dynamically inside method in the class DatePickerComponent?
Thank you for this awnser, i spend all my afternoon trying many aproaches but could not find out, i also tried using MatDateFormat as date format put inside the ngOnInit and worked: """ export const DATE_FORMATS: MatDateFormats = { ...MAT_NATIVE_DATE_FORMATS, display: { ...MAT_NATIVE_DATE_FORMATS.display, dateInput: { year: "numeric", month: "numeric", day: "numeric" }, }, }; """ """ providers: [ { provide: MAT_DATE_FORMATS, useValue: DATE_FORMATS, }, ], """ """ constructor( @Inject(MAT_DATE_FORMATS) public dateFormat: MatDateFormats ) {} public
1

Not too sure how to update the provider's value at runtime, but there is workaround to provide a different MAT_DATE_FORMATS value for mat-datepicker at component level.

As mentioned in Angular Docs:

Components and directives on the same element share an injector.

Place a customPickerFormats directive with a different MAT_DATE_FORMATS provider into the mat-form-field wrapping the mat-datepicker.

in directice.ts:

import { Directive } from '@angular/core';
import { MAT_DATE_FORMATS } from '@angular/material/core';

@Directive({
  selector: '[appCustomPickerFormats]',
  providers: [
    {
      provide: MAT_DATE_FORMATS,
      useValue: {
        parse: {
          dateInput: 'DD/MM',
        },
        display: {
          dateInput: 'Do MMMM',
          monthYearLabel: 'MMM',
          dateA11yLabel: 'LL',
          monthYearA11yLabel: 'MMMM YYYY',
        },
      },
    },
  ],
})
export class CustomPickerFormatsDirective {}

in component.ts:

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

The first mat-datepicker without the directive will by default use whatever MAT_DATE_FORMATS value you set for the HostComponent or the modules the component lays.

enter image description here

A working stackblitz example here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.