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 da
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;
}
}
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: `
<input (click)="picker.open()" [mdDatepicker]="picker" placeholder="Choose a date" [(ngModel)]="datepicker.SearchDate" >
<md-datepicker-toggle mdSuffix [for]="picker"></md-datepicker-toggle>
<md-datepicker #picker touchUi="true" ></md-datepicker>
`,
})
export class App{
datepicker = {SearchDate:new Date()}
constructor( ) {}
}
@NgModule({
declarations: [ App ],
imports: [ CommonModule, BrowserModule, BrowserAnimationsModule, FormsModule, DatePickerModule],
bootstrap: [ App ],
providers: [ ]//NgZone
})
export class AppModule {}
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).
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() {}
}
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
},
...
]
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.