1
votes

I'm new to Angular and I just jumped into an existing project. My issue is about a date picker from angular material. If I select a date via the toggle, no issue, the date is correct but if I want to put a date manually (format used : dd/MM/yyyy), it automatically switch dd and MM as I focus out the input field.

So for example, If I type : "07/04/2019", then I click on the next input I want to change, the date changes to "04/07/2019".

Here is the Input :

<mat-form-field>
    <input matInput [matDatepicker]="availableFrom" placeholder="From" formControlName="availableFrom" (dateChange)="fromDateLessThanToDate()">
    <mat-datepicker-toggle matSuffix [for]="availableFrom"></mat-datepicker-toggle>
    <mat-datepicker #availableFrom></mat-datepicker>
</mat-form-field>

fromDateLessThanToDate() {
    if (DateUtils.fromDateLessThanToDate(this.conventionForm.value.availableFrom, this.conventionForm.value.availableTo))
      this.error_date = { isError: true, errorMessage: 'To date can\'t before From date' };
    else
      this.error_date = { isError: false, errorMessage: '' };
  }

When we arrive in fromDatLessThanToDate() function, the date (this.conventionForm.value.availableFrom) already has a wrong value (days and months switched). I already tested some solutions like this Angular Material mat-datepicker (change) event and format but the result is the same.

1

1 Answers

1
votes

When I had this issue I created this working fix:

import { NativeDateAdapter } from '@angular/material';

export class CustomDateAdapter extends NativeDateAdapter {
  parse(value: any): Date | null {
    if (typeof value === 'string') {
      let str = null;
      if ((value.indexOf('/') > -1)) {
        str = value.split('/');
      } else if ((value.indexOf('-') > -1)) {
        str = value.split('-');
      } else if ((value.indexOf('.') > -1)) {
        str = value.split('.');
      }
      if (str === null) {
        return null;
      }
      const year = Number(str[2]);
      const month = Number(str[1]) - 1;
      const date = Number(str[0]);
      if (month > 11) {
        return new Date(year, date - 1, month + 1);
      }
      return new Date(year, month, date);
    }
    const timestamp = typeof value === 'number' ? value : Date.parse(value);
    return isNaN(timestamp) ? null : new Date(timestamp);
  }
}

This overrides the way the material datepicker parses the date and you have control over it. You can modify the parse method to perform any kind of parse you want.

Then you in your module add the following line in providers array:

import { DateAdapter } from '@angular/material';

@NgModule( {
    { provide: DateAdapter, useClass: CustomDateAdapter }
} )