14

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>

3 Answers 3

10

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

Sign up to request clarification or add additional context in comments.

2 Comments

Instead of returning null you can return this.invalid() which would trigger validation in forms.
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!
2

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!!

Comments

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
        },
     ]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.