Why should I use Validators.compose()?

When we create new FormControl/FormGroup/FormArray(AbstractControl) - coerceToValidator is called.

function coerceToValidator(
    validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null): ValidatorFn|
    null {
  const validator =
      (isOptionsObj(validatorOrOpts) ? (validatorOrOpts as AbstractControlOptions).validators :
                                       validatorOrOpts) as ValidatorFn |
      ValidatorFn[] | null;

  return Array.isArray(validator) ? composeValidators(validator) : validator || null;
}

export function composeValidators(validators: Array<Validator|Function>): ValidatorFn|null {
  return validators != null ? Validators.compose(validators.map(normalizeValidator)) : null;
}

So there is no need to compose validators before we pass it to an AbstractControl.

6/13/16 was added feat(forms): compose validator fns automatically if arrays from now on, Validators.compose is there for backward compatibility.


I know this is an old-ish question, but it came up on a recent search.

The main reason you may want to use Validators.compose() is to reuse multiple validators. Let's say you want to check that a value is between 0 and 100. The first time, you would write:

this.form = this.fb.group({
  foo: [ 0, [ Validators.min(0), Validators.max(100)]]
});

Now let's say you want to do that in several places within your app. To avoid code duplication, you would create your own validator by simply composing it from the existing validators, expose it and reuse it everywhere you need:

// custom-validators.ts
import { Validators } from '@angular/forms';
export class CustomValidators {
  readonly betweenZeroHundred = Validators.compose([
    Validators.min(0),
    Validators.max(100),
  ]);
}

// form1 
this.form = this.fb.group({
  foo: [ 0, [CustomValidators.betweenZeroHundred()]]
});

// form2
this.form = this.fb.group({
  bar: [ 100, [CustomValidators.betweenZeroHundred()]]
});

Nowadays, with the spread operator, you can achieve a similar result, without the compose():

export class CustomValidators {
  readonly betweenZeroHundred = [Validators.min(0), Validators.max(100)];
}

this.form = this.fb.group({
  bar: [ 100, [...CustomValidators.betweenZeroHundred, Validators.required]]
});


In the end, it's a matter of which approach is a better fit for your team and your situation.