Angular 2 Material 2 datepicker date format

JavascriptAngularAngular Material2

Javascript Problem Overview


I need help. I don't know how to change the date format of the material 2 datepicker. I've read documentation but I don't understand what I actually need to do. Output date format which datepicker provides by default is f.e.: 6/9/2017

What I'm trying to achieve is to change format to the 9-Jun-2017 or any other.

Documentation https://material.angular.io/components/component/datepicker doesn't help me at all. Thanks in advance

Javascript Solutions


Solution 1 - Javascript

Here is the only solution I found for this one:

First, create const:

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

Then you have to extend NativeDateADapter:

export class MyDateAdapter extends NativeDateAdapter {
   format(date: Date, displayFormat: Object): string {
       if (displayFormat == "input") {
           let day = date.getDate();
           let month = date.getMonth() + 1;
           let year = date.getFullYear();
           return this._to2digit(day) + '/' + this._to2digit(month) + '/' + year;
       } else {
           return date.toDateString();
       }
   }

   private _to2digit(n: number) {
       return ('00' + n).slice(-2);
   } 
}

In format function, you can choose whatever format you want

And the last step, you have to add it into module providers:

providers: [
    {provide: DateAdapter, useClass: MyDateAdapter},
    {provide: MD_DATE_FORMATS, useValue: MY_DATE_FORMATS},
],

And that's it. I can not believe that there is no some easy way to change date format through the @Input but let's hope it will be implemented in some future version of material 2 (currently beta 6).

Solution 2 - Javascript

Igor's answer didn't work for me so I asked directly on Angular 2 Material's github and someone gave me that answer which worked for me :

  1. First write your own adapter :

     import { NativeDateAdapter } from "@angular/material";
    
    
     export class AppDateAdapter extends NativeDateAdapter {
    
         format(date: Date, displayFormat: Object): string {
    
             if (displayFormat === 'input') {
    
     	        const day = date.getDate();
     	        const month = date.getMonth() + 1;
     	        const year = date.getFullYear();
    
     	        return `${day}-${month}-${year}`;
             }
    
     	    return date.toDateString();
         }
     }
    
  2. Create your date format :

     export const APP_DATE_FORMATS =
     {
         parse: {
     	    dateInput: { month: 'short', year: 'numeric', day: 'numeric' },
         },
         display: {
     	    dateInput: 'input',
     	    monthYearLabel: { year: 'numeric', month: 'numeric' },
     	    dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },
     	    monthYearA11yLabel: { year: 'numeric', month: 'long' },
         }
     };
    
  3. Provide those two to your module

     providers: [
     	    {
     		    provide: DateAdapter, useClass: AppDateAdapter
     	    },
     	    {
     		    provide: MAT_DATE_FORMATS, useValue: APP_DATE_FORMATS
     	    }
         ]
    

More infos here

EDIT: For those who are having the trouble of the manual input is being not respected with the format, you may override the parse(value: any) function from the NativeDateAdapter as follows.

parse(value: any): Date | null {
	const date = moment(value, 'DD/MM/YYYY');
	return date.isValid() ? date.toDate() : null;
}

So, the custom adapter will take the final shape as follows.

import { NativeDateAdapter } from "@angular/material";
import * as moment from 'moment';

export class AppDateAdapter extends NativeDateAdapter {

	format(date: Date, displayFormat: Object): string {
		if (displayFormat === 'input') {

			const day = date.getDate();
			const month = date.getMonth() + 1;
			const year = date.getFullYear();

			return `${day}/${month}/${year}`;
		}

		return date.toDateString();
	}

	parse(value: any): Date | null {
		const date = moment(value, environment.APP_DATE_FORMAT);
		return date.isValid() ? date.toDate() : null;
	}
}

Solution 3 - Javascript

You just need to provide a custom MAT_DATE_FORMATS

export const APP_DATE_FORMATS = {
    parse: {dateInput: {month: 'short', year: 'numeric', day: 'numeric'}},
    display: {
        dateInput: {month: 'short', year: 'numeric', day: 'numeric'},
        monthYearLabel: {year: 'numeric'}
    }
};

and add it to providers.

providers: [{
   provide: MAT_DATE_FORMATS, useValue: APP_DATE_FORMATS
}]

Working code

Solution 4 - Javascript

The work around that works for me is:

my.component.html:

<md-input-container>
  <input mdInput disabled [ngModel]="someDate | date:'d-MMM-y'" >
  <input mdInput [hidden]='true' [(ngModel)]="someDate"  
[mdDatepicker]="picker">
  <button mdSuffix [mdDatepickerToggle]="picker"></button>
</md-input-container>
<md-datepicker #picker></md-datepicker> 

my.component.ts :


@Component({...
})
export class MyComponent implements OnInit {
  ....
  public someDate: Date;
  ...

So now you can have the format (Ex. 'd-MMM-y') that works best for you.

Solution 5 - Javascript

There's a high chance that you already use a library that provides you with an convinient way of manipulating (parsing, validating, displaying, etc.) dates and times in JavaScript. If you dont, take a look at one of them, for example [moment.js][1].

Implementing your custom adapter using moment.js would look like this.

Create CustomDateAdapter.ts and implement it like this:

import { NativeDateAdapter } from "@angular/material";
import * as moment from 'moment';

export class CustomDateAdapter extends NativeDateAdapter {
    format(date: Date, displayFormat: Object): string {
        moment.locale('ru-RU'); // Choose the locale
        var formatString = (displayFormat === 'input')? 'DD.MM.YYYY' : 'LLL';
        return moment(date).format(formatString);
    }
}

In your app.module.ts:

import { DateAdapter } from '@angular/material';

providers: [
    ...
    {
        provide: DateAdapter, useClass: CustomDateAdapter
    },
    ...
]

That's it. Simple, easy and no need of reinventing bicycles. [1]: https://momentjs.com/%22moment.js%22

Solution 6 - Javascript

Create a constant for date format.

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

And Use the below code inside app module

 providers: [
  { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
  { provide: MAT_DATE_FORMATS, useValue: DateFormat }
]

Solution 7 - Javascript

Robouste worked perfect!!

I made easy one (Angular 4 "@angular/material": "^2.0.0-beta.10") first made datepicker.module.ts



import { NgModule }  from '@angular/core';
import { MdDatepickerModule, MdNativeDateModule, NativeDateAdapter, DateAdapter, MD_DATE_FORMATS  }  from '@angular/material';

class AppDateAdapter extends NativeDateAdapter {
    format(date: Date, displayFormat: Object): string {
        if (displayFormat === 'input') {
            const day = date.getDate();
            const month = date.getMonth() + 1;
            const year = date.getFullYear();
            return `${year}-${month}-${day}`;
        } else {
            return date.toDateString();
        }
    }
}

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

@NgModule({
declarations:  [ ],
imports:  [ ],
    exports:  [ MdDatepickerModule, MdNativeDateModule ],
providers: [
{
    provide: DateAdapter, useClass: AppDateAdapter
},
{
    provide: MD_DATE_FORMATS, useValue: APP_DATE_FORMATS
}
]
})

export class DatePickerModule {

}


just import it (app.module.ts)


import {Component, NgModule, VERSION,  ReflectiveInjector}   from '@angular/core'//NgZone,
import { CommonModule }              from '@angular/common';
import {BrowserModule}               from '@angular/platform-browser'
import { BrowserAnimationsModule }        from '@angular/platform-browser/animations';
import { FormsModule }              from '@angular/forms';
import { DatePickerModule }            from './modules/date.picker/datepicker.module';



@Component({
selector: 'app-root',
template: `
&lt;input (click)="picker.open()" [mdDatepicker]="picker" placeholder="Choose a date" [(ngModel)]="datepicker.SearchDate"  &gt;
&lt;md-datepicker-toggle mdSuffix [for]="picker"&gt;&lt;/md-datepicker-toggle>
&lt;md-datepicker #picker touchUi="true"  &gt;&lt;/md-datepicker&gt;
`,
})


export class App{
    datepicker = {SearchDate:new Date()}
    constructor( ) {}

    }

@NgModule({
declarations: [ App ],
imports: [ CommonModule, BrowserModule, BrowserAnimationsModule, FormsModule, DatePickerModule],
bootstrap: [ App ],
providers: [   ]//NgZone
})
export class AppModule {}


Solution 8 - Javascript

Why to not use Angular DatePipe?

import {Component} from '@angular/core';
import {DateAdapter, MAT_DATE_FORMATS, NativeDateAdapter} from '@angular/material';
import {FormControl} from '@angular/forms';
import {DatePipe} 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 new DatePipe('en-US').transform(date, 'EEE, MMM dd, yyyy');
        } else {
            return date.toDateString();
        }
    }
}
@Component({
    selector: 'custom-date',
    template: `<mat-form-field>
                   <input matInput [formControl]="date" />
                   <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
                   <mat-datepicker #picker></mat-datepicker>
               </mat-form-field>`,
    providers: [
        {provide: DateAdapter, useClass: PickDateAdapter},
        {provide: MAT_DATE_FORMATS, useValue: PICK_FORMATS}
    ]
})
export class DateComponent {
    date = new FormControl(new Date());
    constructor() {}
}

Solution 9 - Javascript

original idea of Arthur z and Gil Epshtain, I have changed moment to date-fns. tested in angular @angular/material": "^10.0.2.

Create CustomDateAdapter.ts and implement it like this:

import { NativeDateAdapter } from "@angular/material/core";
import { format } from 'date-fns';
import { es } from 'date-fns/locale'

export class CustomDateAdapter extends NativeDateAdapter {
    format(date: Date, displayFormat: Object): string {
        var formatString = (displayFormat === 'input')? 'DD.MM.YYYY' : 'dd-MM-yyyy';
        return format(date, formatString, {locale: es});
    }
}

In your app.module.ts:

import { DateAdapter } from '@angular/material';

providers: [
    ...
    {
        provide: DateAdapter, useClass: CustomDateAdapter
    },
    ...
]

Solution 10 - Javascript

I used the solution propose by @igor-janković and had the problem of "Error: Uncaught (in promise): TypeError: Cannot read property 'dateInput' of undefined". I realized that this problem was because MY_DATE_FORMATS need to be declare like type MdDateFormats:

export declare type MdDateFormats = {
    parse: {
        dateInput: any;
    };
    display: {
        dateInput: any;
        monthYearLabel: any;
        dateA11yLabel: any;
        monthYearA11yLabel: any;
    };
};

So, the correct way of declare MY_DATE_FORMATS is:

const MY_DATE_FORMATS:MdDateFormats = {
   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'},
   }
};

With the above modification the solution work for me.

Regards

Solution 11 - Javascript

create a file date.adapter.ts

import { NativeDateAdapter, DateAdapter, MAT_DATE_FORMATS, MatDateFormats } from "@angular/material";

export class AppDateAdapter extends NativeDateAdapter {
    parse(value: any): Date | null {
        if ((typeof value === 'string') && (value.indexOf('/') > -1)) {
          const str = value.split('/');
          const year = Number(str[2]);
          const month = Number(str[1]) - 1;
          const date = Number(str[0]);
          return new Date(year, month, date);
        }
        const timestamp = typeof value === 'number' ? value : Date.parse(value);
        return isNaN(timestamp) ? null : new Date(timestamp);
      }
   format(date: Date, displayFormat: string): string {
       if (displayFormat == "input") {
          let day = date.getDate();
          let month = date.getMonth() + 1;
          let year = date.getFullYear();
          return   year + '-' + this._to2digit(month) + '-' + this._to2digit(day)   ;
       } else if (displayFormat == "inputMonth") {
          let month = date.getMonth() + 1;
          let year = date.getFullYear();
          return  year + '-' + this._to2digit(month);
       } else {
           return date.toDateString();
       }
   }
   private _to2digit(n: number) {
       return ('00' + n).slice(-2);
   }
}
export const APP_DATE_FORMATS =
{
   parse: {
       dateInput: {month: 'short', year: 'numeric', day: 'numeric'}
   },
   display: {
       dateInput: 'input',
       monthYearLabel: 'inputMonth',
       dateA11yLabel: {year: 'numeric', month: 'long', day: 'numeric'},
       monthYearA11yLabel: {year: 'numeric', month: 'long'},
   }
}

app.module.ts

  providers: [
    DatePipe,
    {
        provide: DateAdapter, useClass: AppDateAdapter
    },
    {
        provide: MAT_DATE_FORMATS, useValue: APP_DATE_FORMATS
    }
    ]

app.component.ts

import { FormControl } from '@angular/forms';
import { DatePipe } from '@angular/common';
@Component({
  selector: 'datepicker-overview-example',
  templateUrl: 'datepicker-overview-example.html',
  styleUrls: ['datepicker-overview-example.css'],
  providers: [
    DatePipe,
    {
        provide: DateAdapter, useClass: AppDateAdapter
    },
    {
        provide: MAT_DATE_FORMATS, useValue: APP_DATE_FORMATS
    }
    ]
})
export class DatepickerOverviewExample {
  day = new Date();
  public date;
 constructor(private datePipe: DatePipe){
    console.log("anh "," " +datePipe.transform(this.day.setDate(this.day.getDate()+7)));
    this.date = new FormControl(this.datePipe.transform(this.day.setDate(this.day.getDate()+7)));
    console.log("anht",' ' +new Date());
 }
}

app.component.html

<mat-form-field>
  <input matInput [matDatepicker]="picker" placeholder="Choose a date" [formControl]="date">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

Solution 12 - Javascript

angular material date will return the format below (just console.log to see it)

Moment {_isAMomentObject: true, _i: {…}, _isUTC: false, _pf: {…}, _locale: Locale, …} _d: Thu Jan 28 2021 00:00:00 GMT+0800 (Singapore Standard Time) {}

_i: {year: 2021, month: 0, date: 28}

_isAMomentObject: true........

so I convert to short date by using template literals

due_date = ${due_date._i.year}-${due_date._i.month + 1}-${due_date._i.date}

you will get "YYYY-MM-DD" format

Solution 13 - Javascript

This is work for me!

import {Component} from '@angular/core';
import {FormControl} from '@angular/forms';
import {MomentDateAdapter, MAT_MOMENT_DATE_ADAPTER_OPTIONS} from '@angular/material-moment-adapter';
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core';

// Depending on whether rollup is used, moment needs to be imported differently.
// Since Moment.js doesn't have a default export, we normally need to import using the `* as`
// syntax. However, rollup creates a synthetic default module and we thus need to import it using
// the `default as` syntax.
import * as _moment from 'moment';
// tslint:disable-next-line:no-duplicate-imports
import {default as _rollupMoment} from 'moment';

const moment = _rollupMoment || _moment;

// See the Moment.js docs for the meaning of these formats:
// https://momentjs.com/docs/#/displaying/format/
export const MY_FORMATS = {
parse: {
    dateInput: 'LL',
},
display: {
    dateInput: 'LL',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
},
};

/** @title Datepicker with custom formats */
@Component({
selector: 'datepicker-formats-example',
templateUrl: 'datepicker-formats-example.html',
providers: [
    // `MomentDateAdapter` can be automatically provided by importing `MomentDateModule` in your
    // application's root module. We provide it at the component level here, due to limitations of
    // our example generation script.
    {
    provide: DateAdapter,
    useClass: MomentDateAdapter,
    deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS]
    },

    {provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
],
})
export class YourDatepickerUsedComponent {
    date = new FormControl(moment());
}

Link: https://material.angular.io/components/datepicker/examples and search "Datepicker with custom formats"

Solution 14 - Javascript

From documentation:

Customizing the parse and display formats

The MD_DATE_FORMATS object is just a collection of formats that the datepicker uses when parsing and displaying dates. These formats are passed through to the DateAdapter so you will want to make sure that the format objects you're using are compatible with the DateAdapter used in your app. This example shows how to use the native Date implementation from material, but with custom formats.

@NgModule({
  imports: [MdDatepickerModule],
  providers: [
    {provide: DateAdapter, useClass: NativeDateAdapter},
    {provide: MD_DATE_FORMATS, useValue: MY_NATIVE_DATE_FORMATS},
  ],
})
export class MyApp {}
  1. Add required to NgModule.
  2. Create your own format - MY_NATIVE_DATE_FORMATS

Solution 15 - Javascript

Here's my solution with the least amount of code and using the MAT_NATIVE_DATE_FORMATS.

  1. Declare your own date formats
import { MatDateFormats, MAT_NATIVE_DATE_FORMATS } from '@angular/material';

export const GRI_DATE_FORMATS: MatDateFormats = {
  ...MAT_NATIVE_DATE_FORMATS,
  display: {
    ...MAT_NATIVE_DATE_FORMATS.display,
    dateInput: {
      year: 'numeric',
      month: 'short',
      day: 'numeric',
    } as Intl.DateTimeFormatOptions,
  }
};
  1. Use them
@Component({
  selector: 'app-vacation-wizard',
  templateUrl: './vacation-wizard.component.html',
  styleUrls: ['./vacation-wizard.component.scss'],
  providers: [
    { provide: MAT_DATE_FORMATS, useValue: GRI_DATE_FORMATS },
  ]
})

Don't forget to set the appropriate language!

this.adapter.setLocale(this.translate.currentLang);

That's all!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIgor JankovićView Question on Stackoverflow
Solution 1 - JavascriptIgor JankovićView Answer on Stackoverflow
Solution 2 - JavascriptRobousteView Answer on Stackoverflow
Solution 3 - JavascriptAbhishek JhaView Answer on Stackoverflow
Solution 4 - Javascriptluka martinovicView Answer on Stackoverflow
Solution 5 - JavascriptArthur Z.View Answer on Stackoverflow
Solution 6 - JavascriptMohan SinghView Answer on Stackoverflow
Solution 7 - JavascriptYoungHyeong RyuView Answer on Stackoverflow
Solution 8 - JavascriptonalbiView Answer on Stackoverflow
Solution 9 - Javascriptuser12452512View Answer on Stackoverflow
Solution 10 - JavascriptffccView Answer on Stackoverflow
Solution 11 - JavascriptTienanhvnView Answer on Stackoverflow
Solution 12 - JavascriptJeffView Answer on Stackoverflow
Solution 13 - Javascriptlahiru dilshanView Answer on Stackoverflow
Solution 14 - Javascriptandrey.shedkoView Answer on Stackoverflow
Solution 15 - JavascriptNato BoramView Answer on Stackoverflow