Angular 2 Material 2 datepicker date format
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).
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 :
-
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(); } }
-
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' }, } };
-
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;
}
}
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
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.
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.
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.