Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 - Custom validator with dynamic parameter value

I have written a custom validator that checks if a date is above a certain minimum date.

the code looks like this:

export function validateMinDate(min: Date): ValidatorFn {
    return (c: AbstractControl) => {

        if (c == null || c.value == null)
            return null;

        let isValid = c.value >= min;
        if (isValid) {
            return null;
        } else {
            return {
                validateMinDate: {
                    valid: false
                }
            };
        }
    };
}

I initate my form like this

    this.definitionForm = this.fb.group({            
        "from": [this.details.From, Validators.required],
        "to": [this.details.To, [Validators.required, validateMinDate(this.details.From)]]
    });

I can see that the validator is being applied, but when I console.log() my min value in the validator I can see that it equal null.

this.details.From starts at null when I initiate the form, so I assume the parameter is not dynamic and just takes the value when the form is being set?

How can I make sure the min date is being updated when a users picks a from date, and thus changes the value of this.details.From?

like image 720
Nicolas Avatar asked Oct 20 '17 12:10

Nicolas


2 Answers

You can modify your custom validator to take function as parameter like

export function validateMinDate(min: DateFunc): ValidatorFn {
return (c: AbstractControl) => {

    if (c == null || c.value == null)
        return null;

    let isValid = c.value >= min();
    if (isValid) {
        return null;
    } else {
        return {
            validateMinDate: {
                valid: false
            }
        };
    }
};

and initiate the form like this

 this.definitionForm = this.fb.group({            
    ...
    "to": [this.details.To, [Validators.required, validateMinDate(() => this.details.From)]]
});

the DateFunc is just a type that you can create like

export interface DateFunc{
 (): Date
}

and expect this.details.From to return value of type Date

like image 68
newbieCoder Avatar answered Nov 09 '22 03:11

newbieCoder


@Nicolas Validator takes value only once it does not look for it changes. So we can change parameters value dynamically by assigning new validator on value changes. In your case you can do in this way:

 onChanges(){
   var self=this;
    this.definitionForm.get('from').valueChanges.subscribe(val => {
     this.from=val;
     this.definitionForm.controls['to'].
     setValidators(Validators.compose([Validators.required, 
     TimeValidators.isTimeAfter(this.from)]));
})}

Here i created a separate custom validator for comparing the time. You can either use this or modify yours

import { FormControl, Validators,ValidatorFn, AbstractControl} from '@angular/forms';

export class TimeValidators extends Validators{

  static isTimeBefore(timeStr : string): ValidatorFn{
    return(c: AbstractControl): {[key:string]: boolean} | null => {
      if(c.value!==undefined && (isNaN(c.value)) || c.value > timeStr || c.value== timeStr){
        return {
          'isTimeBefore':true
        }
      }
      return null;
    }
  }
  static isTimeAfter(timeStr : string): ValidatorFn{
    return(c: AbstractControl): {[key:string]: boolean} | null => {
      if(c.value!==undefined && (isNaN(c.value)) && (c.value < timeStr || c.value == timeStr)){
        return {
          'isTimeAfter':true
        }
      }
      return null;
    }
  }
}

Call onChanges() function after you initialize your definitionForm FormGroup.

like image 14
dharmendra vaishnav Avatar answered Nov 09 '22 03:11

dharmendra vaishnav