Reputation: 983
I'm setting up a mat-datepicker for DOB and traditionally the display format is MM/DD/YYYY,I need to change it to DD/MM/YYYY with less coding
I tried format tag in mat-date picker but it does not work,other date pickers like ngbDatepicker format can easily changed through one line of coding
<div class="col-md-3 Dinline-block">
<mat-form-field>
<input matInput [matDatepicker]="picker2" [max]="currentDate"
placeholder="DOB(DD/MM/YYYY)" required formControlName="dob"
readonly />
<mat-datepicker-toggle matSuffix [for]="picker2"></mat-datepicker-
toggle>
<mat-datepicker #picker2></mat-datepicker>
</mat-form-field>
</div>
The date displayed after selecting from mat-date picker should be DD-MM-YYYY and when the retrieving the value from date picker it should also be in DD-MM-YYYY format
Upvotes: 96
Views: 240163
Reputation: 1893
I found the ever simple method to convert the date format.
Step 1: Import DatePipe
import { DatePipe } from '@angular/common';
Step 2: Add DatePipe in providers
@Component({
selector: 'your-component',
templateUrl: './your-component.component.html',
styleUrls: ['./your-component.component.css'],
providers:[DatePipe]
})
Step 3: Add DatePipe in constructor
constructor( private _datepipe:DatePipe ) {}
Step 4: Invoke the method to get the date from Date Picker
setDate(dateObject) {
console.log(this._datepipe.transform(dateObject.value, 'dd/MM/YYYY'));
}
Step 5: Your HTML looks like below
<mat-form-field>
<mat-label>Start date</mat-label>
<input matInput [matDatepicker]="date" (dateChange)="setDate($event)">
<mat-datepicker-toggle matIconSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker>
</mat-form-field>
Now you should get the selected date in DD/MM/YYYY format in your console.
Upvotes: 0
Reputation: 81
@Raja code works well for me, here is a small enhansment, this will change the local format when you switch language
constructor(
private dateAdapter: DateAdapter<Date>,
private localizationService: LocalizationService,
)
{}
switchLanguage(lang: string) {
this.currentLanguage = lang;
this.localizationService.setLanguage(lang);
this.dateAdapter.setLocale(lang === 'fr' ? 'fr' : 'en-US');
}
Upvotes: 0
Reputation: 224
you just need to add this line in app module file in providers[]
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' }
Upvotes: 1
Reputation: 801
This bug is very annoying. It exists since 2018, as we all know, and "datepicker: shows date using provided LOCALE_ID but parses date using default US locale" https://github.com/angular/components/issues/14291
We opted for manual data parsing, utilizing the onBlur event. This approach allows us to transform the data from its string representation and subsequently set the form value to an ISO date format conforming to the European standard.
view:
<input
matInput
(blur)="onDateInputed($event)"
[min]="minDate"
[matDatepicker]="datePicker" />
and component:
onDateInputed($event: any) {
const dateString = $event.target.value;
const parts = dateString.split('/');
const day = parseInt(parts[0], 10);
const month = parseInt(parts[1], 10) - 1; // Months are zero-based in JavaScript
const year = parseInt(parts[2], 10);
const parsedDate = new Date(year, month, day);
console.log(parsedDate);
this.formGroup.controls['dateControl'].setValue(parsedDate);
}
Upvotes: 4
Reputation: 1280
{ provide: MAT_DATE_FORMATS, useValue: ISO_FORMAT },
export const ISO_FORMAT = {
parse: {
dateInput: 'DD/MM/YYYY',
},
display: {
dateInput: 'DD/MM/YYYY',
monthYearLabel: 'MMM YYYY',
dateA11yLabel: 'LL',
monthYearA11yLabel: 'MMMM YYYY',
},
};
Upvotes: 0
Reputation: 425
First, bind the format to your mat-datepicker.
export const MY_FORMATS = {
parse: {
dateInput: 'LL'
},
display: {
dateInput: 'YYYY-MM-DD',
monthYearLabel: 'YYYY',
dateA11yLabel: 'LL',
monthYearA11yLabel: 'YYYY'
}
};
along with this you need to import and provide the modules.
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material';
import { MomentDateModule, MomentDateAdapter } from '@angular/material-moment-adapter';
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS }
And in HTML follow this simply.
<mat-form-field>
<input
matInput
[matDatepicker]="dp"
placeholder="Some verbose datepicker"
[formControl]="date"
>
<mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
<mat-datepicker #dp></mat-datepicker>
</mat-form-field>
Upvotes: 40
Reputation: 1
import { DateAdapter } from '@angular/material/core';
constructor( private dateAdapter: DateAdapter<Date>) {
this.dateAdapter.setLocale('sv-se');
}
Upvotes: 0
Reputation: 2973
Solution 1: Either you can declare in your individual module/shared module or app.module.ts
providers: [
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' },
]
Solution 2:
import { DateAdapter } from '@angular/material';
constructor(private dateAdapter: DateAdapter<Date>) {
this.dateAdapter.setLocale('your locale');
}
Upvotes: 6
Reputation: 71
In case you want to have 100% control here is solution I came up with using date-fns all the way.
Component
export const MY_DATE_FORMATS = {
parse: {
dateInput: ["dd.MM.yyyy", "dd/MM/yyyy", "dd,MM,yyyy"], // to accept different input styles from user
},
display: {
dateInput: "dd.MM.yyyy", // display format in input field
monthYearLabel: 'yyyy MMMM',
dateA11yLabel: 'MMMM d, y',//'LL',
monthYearA11yLabel: 'MMMM yyyy'
},
};
@Component({
providers: [
{ provide: MAT_DATE_LOCALE, useValue: nb },
{ provide: DateAdapter, useClass: YourCustomDateAdapter },
{ provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMATS },
],
})
Adapter
I had to write my own adapter, because DateFnsAdapter use parseISO(), and that is not what I want. All I need to do is to override parsing.
@Injectable()
export class YourCustomDateAdapter extends DateFnsAdapter {
//this parses date from input field
override parse(value: any, parseFormat: string | string[]): Date | null {
if (typeof value == 'string' && value.length > 0) {
if (!parseFormat.length) throw Error('Formats array must not be empty.');
for (const currentFormat of parseFormat) {
const fromFormat = parse(value, currentFormat, new Date(), {locale: this.locale});
if (this.isValid(fromFormat)) {
return fromFormat;
}
}
return this.invalid();
} else if (typeof value === 'number') {
return new Date(value);
} else if (value instanceof Date) {
return this.clone(value);
}
return null;
}
}
Component
Last piece of puzzle is how to control output format from datepicker component. I prefer to use FormControl for the input field (it can be done also with ngModel + ngModelChanges if you like)
@Input() config: DateFormatOutputFNS = DateFormatOutputFNS["yyyy-mm-dd"];
this.local_control.valueChanges.subscribe(v => {
if (isValid(v)){ //to avoid sending output as user type into input field
if (this.withinRange(v)){ // add you validation logic as you like
this.control.setValue(format(v, this.config))
this.control.markAsDirty()
this.control.markAsTouched()
}
}
})
Config options
refer to this.config above. Add output format options as you like according to date-fns formats
export enum DateFormatOutputFNS {
"yyyy-mm-dd" = "yyyy-MM-dd",
"yyyy-mm-ddT00:00:00Z" = "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'",
}
Upvotes: 4
Reputation: 46
MomentDateAdapter v8.1.4 is working fine with my project running angular v12.2.0. However I was unable to use MomentDateAdapter versions ranging from 12.2 to 13.2. V8.1.4 seems to be working fine
heres the import array I used in my app module:
import { LOCALE_ID} from '@angular/core';
import {
DateAdapter,
MAT_DATE_FORMATS,
MAT_DATE_LOCALE,
} from '@angular/material/core';
import { MomentDateAdapter } from '@angular/material-moment-adapter';
export const DATE_FORMATS = {
parse: {
dateInput: 'DD.MM.YYYY',
},
display: {
dateInput: 'DD.MM.YYYY',
monthYearLabel: 'MMM YYYY',
dateA11yLabel: 'LL',
monthYearA11yLabel: 'MMMM YYYY',
},
};
providers: [
{ provide: DateAdapter, useClass:MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
{ provide: MAT_DATE_FORMATS, useValue: DATE_FORMATS },
{ provide: LOCALE_ID, useValue: 'de-DE' }, // for German translation. Ignore this if not needed.
],
Upvotes: 1
Reputation: 2858
The easiest way is to change the locale:
Add the following to the providers section of your module:
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' }
Upvotes: 133
Reputation: 621
I got it working after combining some knowledge from various answers here, so I thought I'd consolidate what worked for me.
In your module, import MAT_DATE_LOCALE and add it to providers:
import { MAT_DATE_LOCALE } from '@angular/material/core'
@NgModule({
declarations: [...],
imports: [...],
exports: [...],
providers: [
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' }
]
})
If you use a shared module to import material this will change all the formats of your datepickers across the site.
Upvotes: 25
Reputation: 2293
Install "@angular/material-moment-adapter" the version of you angular
npm i @angular/material-moment-adapter@[your_angular_version] find the version
Install "moment"
npm i moment
Create a configuration on how you want the date to be displayed and parsed.
const MY_DATE_FORMAT = {
parse: {
dateInput: 'DD/MM/YYYY', // this is how your date will be parsed from Input
},
display: {
dateInput: 'DD/MM/YYYY', // this is how your date will get displayed on the Input
monthYearLabel: 'MMMM YYYY',
dateA11yLabel: 'LL',
monthYearA11yLabel: 'MMMM YYYY'
}
};
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MomentDateAdapter } from '@angular/material-moment-adapter';
{ provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
{ provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMAT }
This answered is inspired by this anwer
Upvotes: 55
Reputation: 13318
Angular 12 tested.
In the below chunk of code you can see how you can inject the datepipe into the constructor and then you can use it to convert date format in date controls. The best thing about this solution is that you are free to form the date as you wish regardless of any locale restrictions:
import { DatePipe } from '@angular/common';
export class SomeComponent {
myDatepipe!: any;
constructor(private fb: FormBuilder, datepipe: DatePipe)
{
this.myDatepipe = datepipe;
this.someForm = this.fb.group({
someDateControl : new FormControl()
});
}
SomeAction()
{
if(this.someForm.value.someDateControl)
{
const ConvertedDate = this.myDatepipe.transform(this.someForm.value.someDateControl, 'yyyy-MM-dd');
}
}
}
Upvotes: 0
Reputation: 29
If you want to change the MaterialDatePicker date format into yyyy-mm-dd then use the below code. This code is working for me.
MaterialDatePicker<Long> materialDatePicker=materialDateBuilder.build();
materialDatePicker.addOnPositiveButtonClickListener(new MaterialPickerOnPositiveButtonClickListener<Long>() {
@Override
public void onPositiveButtonClick(Long selection) {
// Get the offset from our timezone and UTC.
TimeZone timeZoneUTC = TimeZone.getDefault();
// It will be negative, so that's the -1
int offsetFromUTC = timeZoneUTC.getOffset(new Date().getTime()) * -1;
// Create a date format, then a date object with our offset
SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
Date date = new Date(selection + offsetFromUTC);
mEt_last_date_to_apply.setText(simpleFormat.format(date));
}
});
mEt_last_date_to_apply is my EditText
Upvotes: 0
Reputation: 2711
For me, the best approach was to inject MAT_DATE_FORMATS
to my component, which then dynamically determines what should the display format look like.
Setup in component:
constructor(@Inject(MAT_DATE_FORMATS) private dateFormats) { }
ngOnInit() {
if (this.data.inputType === InputDateDialogRangeType.MonthAndYearOnly)
this.dateFormats.display.dateInput = "MMMM YYYY";
else if (this.data.inputType === InputDateDialogRangeType.YearOnly)
this.dateFormats.display.dateInput = "YYYY";
}
Setup in module:
providers: [
{ provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMAT },
{
provide: DateAdapter,
useClass: MomentDateAdapter,
deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS]
},
{ provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } },
export const MY_DATE_FORMAT = {
display: {
dateInput: 'DD MMM YYYY',
monthYearLabel: 'MMM YYYY',
dateA11yLabel: 'LL',
monthYearA11yLabel: 'MMMM YYYY',
},
};
Upvotes: 3
Reputation: 447
use dateadapter from core
import { DateAdapter } from '@angular/material/core';
constructor(private dateAdapter: DateAdapter<Date>) {
this.dateAdapter.setLocale('en-GB'); //dd/MM/yyyy
}
`
Upvotes: 37
Reputation: 17
add to the providers list:
{provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
Upvotes: -1
Reputation: 221
Try this in the component you are using mat-datepicker
import { DateAdapter } from '@angular/material';
constructor(private dateAdapter: DateAdapter<Date>) {
this.dateAdapter.setLocale('your locale');
}
Upvotes: 17