3

I want to write a custom dateValidator with reactive forms to check if an inputed date is before today.

Component.html

<form class="container" [formGroup]="form" (ngSubmit)="submit()">
  <div mat-dialog-content>
    ...
    <mat-form-field>
      <mat-label>Birthday</mat-label>
      <input  matInput [matDatepicker]="birthdayDatepicker" formControlName="birthday">
      <mat-datepicker-toggle matSuffix [for]="birthdayDatepicker"></mat-datepicker-toggle>
      <mat-datepicker #birthdayDatepicker></mat-datepicker>
    </mat-form-field>
  </div>
</form>

Component.ts

  ngOnInit() {
    this.form = this.fb.group({
      name : [,Validators.required],
      email: [,Validators.email],
      birthday: [,dateValidator],
      role: [,Validators.required]
    });
  }

What can write here? I would like the value of the input to be lower than today : value < new Date()

export function dateValidator(): ValidatorFn {
  ...
}
jtobelem
  • 749
  • 2
  • 6
  • 23
  • Does this answer your question? [Compare two dates with JavaScript](https://stackoverflow.com/questions/492994/compare-two-dates-with-javascript) – Trenton Trama Apr 29 '20 at 13:59
  • no, the comparaison is ok with the '<' comparator. My question is about writing the ValidatorFn and the synthax of this function – jtobelem Apr 29 '20 at 14:04

2 Answers2

4

Since you are asking for the ValidationFn syntax, it may look like this:

dateValidator(control: FormControl): { [s: string]: boolean } {
    // implementation of the validation
}

Usage:

ngOnInit() {
  this.form = this.fb.group({
    name : [,Validators.required],
    email: [,Validators.email],
    birthday: [,this.dateValidator],
    role: [,Validators.required]
  });
}

With moment library:

import * as moment from 'moment';

[...]

dateValidator(control: FormControl): { [s: string]: boolean } {
  if (control.value) {
    const date = moment(control.value);
    const today = moment();
    if (date.isBefore(today)) {
      return { 'invalidDate': true }
    }
  }
  return null;
}
hpopiolkiewicz
  • 3,281
  • 4
  • 24
  • 36
2

You can see the Stackblitz demo here.

export function dateValidator(): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} | null => {
    const today = new Date().getTime();

    if(!(control && control.value)) {
      // if there's no control or no value, that's ok
      return null;
    }

    // return null if there's no errors
    return control.value.getTime() > today 
      ? {invalidDate: 'You cannot use future dates' } 
      : null;
  }
}

And you can use like this:

ngOnInit() {
    this.form = this.fb.group({
      ...
      birthday: [new Date(), dateValidator()],
      ...
    });
  }
julianobrasil
  • 8,954
  • 2
  • 33
  • 55
  • tks @julianobrasil! that is what I looked for. Unfortunately, the validator is not called as I enter the value using a datePicker. But it is maybe another issue. – jtobelem Apr 29 '20 at 14:22
  • 1
    I've put a demo link in my answer. Take a look. – julianobrasil Apr 29 '20 at 14:51
  • tks a lot!! I used date: [new Date(), dateValidator] without parenthesis (strangely, the code before the return was hit (I try with a console). Now it's fine. – jtobelem Apr 29 '20 at 17:19