Olivier
Olivier

Reputation: 445

Get specific format with material datePicker

I’m working on an app that uses an angular material datepicker.

This datepicker returns a date object in ISO 8601 format I want to get the format yyyy-MM-dd in string. For this, I created the following code:

HTML:

  <mat-form-field class="example-full-width" appearance="fill">
    <mat-label>{{ 'commons.consultations.dateTo' | translate }}</mat-label>
    <input matInput [matDatepicker]="pickerTo" formControlName="dateTo" />
    <mat-datepicker-toggle
      matSuffix
      [for]="pickerTo"
    ></mat-datepicker-toggle>
    <mat-datepicker
      (closed)="convertDateTo_YYYY_MM_DD_Format()"
      #pickerTo
    ></mat-datepicker>
  </mat-form-field>

ts file:

  public convertDateTo_YYYY_MM_DD_Format() {
    this.form
      .get('dateTo')
      ?.setValue(
        this.datePipe.transform(this.form.get('dateTo')?.value, 'yyyy-MM-dd')
      );
  }

module.ts (format fr-FR)

providers: [{ provide: MAT_DATE_LOCALE, useValue: 'fr-FR' }, DatePipe]

In my code, I have a custom validator that checks that the date is in the format yyyy-MM-dd:

export function dateValidator(
  dateTo: string,
): ValidatorFn {
  return (form: AbstractControl): ValidationErrors | null => {
    let dateTo = form.get(dateTo );
    const regEx = /^[12]\d{3}-\d{2}-\d{2}$/;

    //...............

    if (dateTo.value?.match(regEx)) {
          // do some stuff.....................
}

The problem with this code is that the validator is triggered even before the function call that depends on the event datepicker (closed).

(closed)=convertDateTo_YYYY_MM_DD_Format()

My question is: is there a way for the datepicker itself to convert the date to the desired format (yyyy-MM-dd) without going through the closed event before the validator is triggered?

Thanks for your help

Upvotes: 0

Views: 262

Answers (1)

Nikhil Makwana
Nikhil Makwana

Reputation: 1014

There is a way to get the desired date format directly from the datepicker without relying on the closed event. You can use the MatDatepickerInputEvent that is emitted when the user selects a date, and then convert the selected date to the desired format using the DatePipe. Here's an example:

HTML

<mat-form-field class="example-full-width" appearance="fill">
  <mat-label>{{ 'commons.consultations.dateTo' | translate }}</mat-label>
  <input matInput [matDatepicker]="pickerTo" formControlName="dateTo" (dateChange)="onDateChange($event)" />
  <mat-datepicker-toggle matSuffix [for]="pickerTo"></mat-datepicker-toggle>
  <mat-datepicker #pickerTo></mat-datepicker>
</mat-form-field>

TS file

import { DatePipe } from '@angular/common';

constructor(private datePipe: DatePipe) {}

public onDateChange(event: MatDatepickerInputEvent<Date>) {
  const formattedDate = this.datePipe.transform(event.value, 'yyyy-MM-dd');
  this.form.get('dateTo')?.setValue(formattedDate);
}

Updated Code using subscribe method

HTML

<mat-form-field class="example-full-width" appearance="fill">
  <mat-label>{{ 'commons.consultations.dateTo' | translate }}</mat-label>
  <input matInput [matDatepicker]="pickerTo" formControlName="dateTo" />
  <mat-datepicker-toggle matSuffix [for]="pickerTo"></mat-datepicker-toggle>
  <mat-datepicker #pickerTo></mat-datepicker>
</mat-form-field>

TS

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DatePipe } from '@angular/common';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
})
export class ExampleComponent implements OnInit {
  form: FormGroup;
  dateToSubscription: Subscription;

  constructor(
    private fb: FormBuilder,
    private datePipe: DatePipe
  ) {}

  ngOnInit() {
    this.form = this.fb.group({
      dateTo: ['', Validators.required],
    });

    // Subscribe to the valueChanges of dateTo form control
    this.dateToSubscription = this.form
      .get('dateTo')
      .valueChanges.subscribe((dateTo: Date) => {
        // If the date is valid, format it and update the form control value
        if (dateTo instanceof Date && !isNaN(dateTo.getTime())) {
          const formattedDate = this.datePipe.transform(dateTo, 'yyyy-MM-dd');
          this.form.get('dateTo').setValue(formattedDate);
        }
      });
  }

  ngOnDestroy() {
    this.dateToSubscription.unsubscribe();
  }
}

Upvotes: 0

Related Questions