Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 670
Martijn van den Bergh Avatar asked Jan 05 '21 14:01

Martijn van den Bergh


People also ask

How can use datepicker in angular materials?

mat-datepicker exampleAdd a template reference variable mat-datepicker element. Connect mat-datepicker to input element via [matDatepicker] property. Finally add date picker toggle button to display or hide calender popup by using mat-datepicker-toggle element.

How do you use datepicker material?

Connecting a datepicker to an input A datepicker is composed of a text input and a calendar pop-up, connected via the matDatepicker property on the text input. There is also an optional datepicker toggle button that gives the user an easy way to open the datepicker pop-up.


3 Answers

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 { }
like image 85
Martijn van den Bergh Avatar answered Nov 15 '22 04:11

Martijn van den Bergh


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}
]
like image 20
Ivan Zinchenko Avatar answered Nov 15 '22 04:11

Ivan Zinchenko


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.

like image 32
Rory Avatar answered Nov 15 '22 03:11

Rory