angularangular-reactive-formsangular-validationangular-custom-validators

Angular - Custom form validator


I have two mandatory form controls as: minimumCharacters and maximumCharacters. I want to show an error, if the given maximumCharacters is smaller than the given minimumCharacters. Here is how I have defined my form:

this.form.addControl('minimumCharacters', this.formBuilder.control(1, [Validators.required]),{ emitEvent: false });

this.form.addControl('maximumCharacters', this.formBuilder.control('', [maximumCharactersValidator(1)]), { emitEvent: false});

And here is my maximumCharactersValidator:

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


export function maximumCharactersValidator(minValue: number): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
        console.log("control.value: ", control.value);
        let maxValue = control.value;
        if (maxValue > minValue) {
            return { maximumCharactersValid: true}
        }
        else {
            return { maximumCharactersValid: false}
        }
        return null;
    }
}

But this way I don't have access to the control value!


Solution

  • You can work with control.parent to get the parent form group and get the control with name: "minValue"

    If the validation is true, you should return { maximumCharactersValid: null } to represent no error. Returning { maximumCharactersValid: true } mean the validation failed.

    export function maximumCharactersValidator(): ValidatorFn {
      return (control: AbstractControl): ValidationErrors | null => {
        let minValue = (control.parent as FormGroup)?.get("minimumCharacters")!.value;
    
        let maxValue = control.value;
        if (maxValue > minValue) {
          return null;
        } else {
          return { maximumCharactersValid: true };
        }
      }
    }
    

    When you add the validator, you don't need to provide the argument.

    this.form.addControl('maximumCharacters', 
      this.formBuilder.control('', [maximumCharactersValidator()]), { emitEvent: false});
    

    Demo @ StackBlitz