'How can I format the Angular Material datepicker without moment.js dependency

What do I want to achieve?

I want my Angular Material(v11) datepicker to use the DD-MM-YYYY format in an Angular version 11 project.

What have I tried?

I tried using the MatMomentDateModule but this uses the moment.js library. This in turn will use all the locales in the bundle, which inceases the bundle size with 400kb. I have added CUSTOM_DATE_FORMATS to the providers of my app.module.ts which looks like this:

const CUSTOM_DATE_FORMATS = {
    parse: {
        dateInput: 'DD-MM-YYYY',
    },
    display: {
        dateInput: 'DD-MM-YYYY',
        monthYearLabel: 'MMMM YYYY',
        dateA11yLabel: 'LL',
        monthYearA11yLabel: 'MMMM YYYY',
    },
};

And this works but as mentioned before, the bundle size increases severely and i don't use any locales.

Is there a way to do format my date DD-MM-YYYY, without the use of the moment.js library?

or

Is the moment.js treeshakable in a way so that i only use the stuff that i need?



Solution 1:[1]

So i didn't knew if you used the MatNativeDateModule that you could also implement a custom date adapter. I thought this was something that was specific to MatMomentDateModule.

Once I figured this out i could just overwrite the format function and format it manually likes so:

export class CustomDateAdapter extends NativeDateAdapter {
    format(date: Date, displayFormat: any): string {
        const days = date.getDate();
        const months = date.getMonth() + 1;
        const year = date.getFullYear();
        return days + '-' + months + '-' + year;
    }
}

And implement it like so:

@NgModule({

  providers: [
    {
      provide: DateAdapter,
      useClass: AppDateAdapter,
      deps: [MAT_DATE_LOCALE, Platform]
    },
  ]

})
export class AppModule { }

Solution 2:[2]

Had the same issue myself today and did not want to use moment.js. It seems if you only want a standard date format (e.g. non-US) a simple solution is to add to your app.module.ts:

import { MAT_DATE_LOCALE } from '@angular/material/core';
@NgModule({
...
  providers: [{provide: MAT_DATE_LOCALE, useValue: 'en-GB'}],
...

No doubt other country codes would also work. This approach presumably changes all date appearances across your application (not just your datepicker) but in my case this was perfectly acceptable. No further changes were required in the component nor HTML template.

Solution 3:[3]

Found this solution here and it works as intended https://www.angularjswiki.com/material/datepicker/#mat-datepicker-date-format

import { NativeDateAdapter, DateAdapter,MAT_DATE_FORMATS } from '@angular/material';
import { formatDate } from '@angular/common';

export const PICK_FORMATS = {
  parse: {dateInput: {month: 'short', year: 'numeric', day: 'numeric'}},
  display: {
      dateInput: 'input',
      monthYearLabel: {year: 'numeric', month: 'short'},
      dateA11yLabel: {year: 'numeric', month: 'long', day: 'numeric'},
      monthYearA11yLabel: {year: 'numeric', month: 'long'}
  }
};

class PickDateAdapter extends NativeDateAdapter {
  format(date: Date, displayFormat: Object): string {
      if (displayFormat === 'input') {
          return formatDate(date,'dd-MMM-yyyy',this.locale);;
      } else {
          return date.toDateString();
      }
  }
}

And then just use it in your module or component providers

providers: [
    {provide: DateAdapter, useClass: PickDateAdapter},
    {provide: MAT_DATE_FORMATS, useValue: PICK_FORMATS}
]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Rory
Solution 3 Ivan Zinchenko