RezaNikfal
RezaNikfal

Reputation: 993

Issue with Angular Material date picker validation

I am validating a simple Angular Material date picker. It is weird because when I click on the little calendar it works fine but as soon as I click on the input field and before picking the date, the color becomes red as follows:

enter image description here

Here is the markup template:

    <mat-form-field class="datePicker">
        <input matInput [matDatepicker]="picker" (click)="picker.open()" readonly=true
            placeholder="Choose a date range" formControlName="dateRange">
        <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
        <mat-datepicker #picker></mat-datepicker>
    </mat-form-field>

And here is the typescript:

export class TrackingPanelComponent {


  toppingList: string[] = ['Machine A', 'Machine B', 'Machine C', 'Machine D'];

  constructor(private fb: FormBuilder) { }

  formGroup = this.fb.group({
    selectMachine: [null, Validators.required],
    dateRange: [null, Validators.required],
    trackingPath: [false],
    latestPosition: [false]
  })

  clearAll(){
    this.formGroup.reset()
  }
}

I know it is because of (click)="picker.open()" but I need to keep it to open the date picker easier. Any Idea to fix it?

Upvotes: 4

Views: 4477

Answers (1)

Pieter Buys
Pieter Buys

Reputation: 1340

The problem is that normally clicking on an input adds focus to it. However when calling the picker.open() method we lose focus immediately - which results in the validator registering a touch and therefore showing a validation error. Here's what I did

1 Disable default focus behaviour

We want to prevent the browser add focus on mouseDown (notice we bind to (mousedown) instead of (click) because that is where focus will happen by default)

(mousedown)="picker.open();$event.preventDefault()"

2 Validate form when datepicker closes

I did this by calling markAsTouched on formControl. Note - rather bind to method in the component.ts file.

<mat-datepicker #picker (closed) = "formGroup.get('dateRange').markAsTouched()"></mat-datepicker>

Complete example

<mat-form-field class="datePicker">
   <input matInput [matDatepicker]="picker" 
       (mousedown)="picker.open(); $event.preventDefault" 
       readonly=true
       placeholder="Choose a date range" formControlName="dateRange">
   <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
   <mat-datepicker #picker 
      (closed) = "formGroup.get('dateRange').markAsTouched()"></mat-datepicker>
</mat-form-field>

Upvotes: 7

Related Questions