Validation on Custom Form Control

We use the Validator interface to add custom validation to our form controllers. The Validator interface provides the following two methods responsible for the form validation.

interface Validator {
  validate(control: AbstractControl): ValidationErrors | null;
  registerOnValidatorChange?(fn: () => void): void;
class EmailValidator implements Validator {
  private _onChange?: () => void;

  set email(value: boolean | string) {
    if (this._onChange) this._onChange();

  validate(control: AbstractControl): ValidationErrors | null {
    return emailValidator(control);

  registerOnValidatorChange(fn: () => void): void {
    this._onChange = fn;

We also have an AsyncValidator to implement asynchronous validations. The success of synchronous validators will trigger asynchronous validations. So, if we've any failing synchronous validators, then asynchronous will not be triggered.

interface AsyncValidator extends Validator {
    control: AbstractControl
  ): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;

The observable returned via validate must be finite, meaning it must complete at some point.