Angular Material Datepicker input format
Asked Answered
M

3

13

When selecting a date with the datepicker, everything works great, displaying the date in the desired format: DD/MM/YYYY

But when entering manually a date with format DD/MM/YYYY, the datepicker automatically changes the date to MM/DD/YYYY, detecting the first value DD as a month.

How can I make the manual input be detected as DD/MM/YYYY, not as MM/DD/YYYY?

Thanks!

<mat-form-field class="datepickerformfield" floatLabel="never">
    <input matInput class="dp" formControlName="fpresentaciondesde" [matDatepicker]="picker5" placeholder="DD/MM/YYYY" required>
    <mat-datepicker-toggle matSuffix [for]="picker5"></mat-datepicker-toggle>
    <mat-datepicker #picker5></mat-datepicker>
</mat-form-field>
Myalgia answered 27/9, 2019 at 10:0 Comment(0)
T
9

You need to build a custom date adapter like this:

export class CustomDateAdapter 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: Object): string {
    date = new Date(Date.UTC(
      date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(),
      date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
    displayFormat = Object.assign({}, displayFormat, { timeZone: 'utc' });

    const dtf = new Intl.DateTimeFormat(this.locale, displayFormat);
    return dtf.format(date).replace(/[\u200e\u200f]/g, '');
  }

}

and then use it in your app:

@NgModule({
    ....
    providers: [
        { provide: DateAdapter, useClass: CustomDateAdapter }
    ]
})

DEMO

Tierney answered 27/9, 2019 at 11:3 Comment(2)
Instead of returning null you can return this.invalid() which would trigger validation in forms.Forelock
True. I wondered why the input jumped back to "mm.dd.yyyy" after pressing enter. That`s because your post answered the OP's questions for '/'-splitted "dd/mm/yyyy" and I had to adept it for use with dot-splitted format. Shame On me!Maxson
S
1

HTML code

<mat-form-field>
<input matInput placeholder=”Select Date” [matDatepicker]=”datepickerRef” name=”datepicker” ngModel #dateCtrl=”ngModel” required readonly/>
<mat-datepicker-toggle [for]=”datepickerRef” matSuffix></mat-datepicker-toggle>
<mat-datepicker #datepickerRef></mat-datepicker>
<mat-error *ngIf=”dateCtrl.errors?.required && deptCtrl.touched”>Choose a Date</mat-error>
</mat-form-field>

This is the helper function write on file name format-datepicker.ts

import { NativeDateAdapter } from ‘@angular/material’;
import { MatDateFormats } from ‘@angular/material/core’;
export class AppDateAdapter extends NativeDateAdapter {
  format(date: Date, displayFormat: Object): string {
    if (displayFormat === ‘input’) {
      let day: string = date.getDate().toString();
      day = +day < 10 ? ‘0’ + day : day;
      let month: string = (date.getMonth() + 1).toString();
      month = +month < 10 ? ‘0’ + month : month;
      let year = date.getFullYear();
      return `${day}-${month}-${year}`;
    }
    return date.toDateString();
  }
}
export const APP_DATE_FORMATS: MatDateFormats = {
  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 above implementation inside the providers tag.

import {DateAdapter, MAT_DATE_FORMATS} from '@angular/material/core';
import { AppDateAdapter, APP_DATE_FORMATS } from 'src/app/shared/format-datepicker';
@Component({
  providers: [
    {provide: DateAdapter, useClass: AppDateAdapter},
    {provide: MAT_DATE_FORMATS, useValue: APP_DATE_FORMATS}
  ]
})

I tried this out by using this article https://amandeepkochhar.medium.com/angular-material-datepicker-set-custom-date-in-dd-mm-yyyy-format-5c0f4340e57 and it works!!

Superimposed answered 12/7, 2021 at 23:37 Comment(0)
M
0

Support input format DD.MM.YY and DD.MM.YYYY

File ru-date-adapter.ts

import { Injectable } from "@angular/core";
import { MatDateFormats, NativeDateAdapter } from "@angular/material/core";

@Injectable()
export class DateAdapterRus extends NativeDateAdapter {
    
    override getFirstDayOfWeek(): number {
        return 1;
    }

    override parse(value: any, parseFormat?: any): Date | null{
        if (parseFormat == 'DD.MM.YYYY' || parseFormat == 'DD.MM.YY'){
            let dateParts = value.match(/(\d{1,2}).(\d{1,2}).(\d{2,4})/)
            if (dateParts) {
                let day = dateParts[1]
                let month = dateParts[2]
                let year = dateParts[3]
                if (year.length == 2){
                    let currentDate = new Date()
                    year = currentDate.getFullYear().toString().slice(0,2) + year
                }
                let data = new Date(Date.parse(`${year}-${month}-${day}`))
                return data
            }
        }
        let data = super.parse(value, parseFormat)
        return data
    }
}

export const RUS_DATE_FORMATS: MatDateFormats = {
    parse: {
        dateInput: 'DD.MM.YYYY',
    }, 
    display: {
        dateInput: 'DD.MM.YYYY',
        monthYearLabel: 'MMM YYYY',
        dateA11yLabel: 'LL',
        monthYearA11yLabel: 'MMMM-YYYY',
    },
}

Module file app.module.ts

    providers: [
        {
            provide: DateAdapter, useClass: DateAdapterRus
        },
        {
            provide: MAT_DATE_FORMATS, useValue: RUS_DATE_FORMATS
        },
     ]
Manicurist answered 23/3, 2023 at 18:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.