angularangular-reactive-formsangular-validation

Custom Validator in Angular Reactive Forms not working


I have a custom validator on the field postalCode:

function postalCodeValidator(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    if (!this.contactForm) {
      return null;
    }

    const isPotalCodeRequired = this.contactForm.get(
      'isPotalCodeRequired'
    ).value;

    if (isPotalCodeRequired && !control.value) {
      console.log('here');
      this.contactForm.controls['postalCode'].setErrors({ required: true });
    } else {
      this.contactForm.controls['postalCode'].setErrors({ required: false });
    }

    return null;
  };
}

which checks another field isPotalCodeRequired to see if validation should be applied to the postalCode field or not.

If isPotalCodeRequired is true, a value is required for postalCode else it can be left empty. But my custom validation doesn't seem to work as expected when I call setErrors on the postalCode field. It adds it, within the custom validator function, but checking it after the function executes, the error is no longer present on the postalCode field.

Demo.


Solution

  • Angular's validator functions are a little bit weird. You need to return null when the control has no errors and an object containing the errors and a brief description when they are incorrect:

    function postalCodeValidator(): ValidatorFn {
      return (control: AbstractControl): ValidationErrors | null => {
        if (!this.contactForm) {
          return null;
        }
    
        const isPotalCodeRequired = this.contactForm.get(
          'isPotalCodeRequired'
        ).value;
    
        if (isPotalCodeRequired && !control.value) {
          console.log('here');
          return {required: 'Postal code is required' };
        }
    
        return null;
      };
    }
    
    

    You don't need to manually set the errors as the framework will do it for you