Custom Validators for Angular Reactive Forms

Image of a screen of code

Angular… ugh, I know.

But Reactive Forms are actually pretty cool and once you get the hang of them, you can appreciate all of the form dynamics that Angular handles for you.

At the end of the day we want to supply an object to a form, allow the user to make changes and keep those changes valid.

Angular provides classes to marry object properties to markup and a convenient FormBuilder to help construct groups of form components with default values.

this.formGroup = formBuilder.group([
  {
    "name": [
      "Adam",
    ],
    "age": [
      "21"
    ]
  }
]);

Out of the box Angular provides a set of validators that cover many if not most requirements.

My name should be longer than 20 characters and clearly I’m no older than 25 so I can specify validators to the FormBuilder object:

this.formGroup = formBuilder.group([
  {
    "name": [
      "Adam", Validators.maxLength(20)
    ],
    "age": [
      "21", Validators.max(25)
    ]
  }
]);

We can check for validation errors in our FormGroup object with the errors property of each control. This property maintains an object that, when the value is valid, is empty. Otherwise, the object contains keys indicating how the value has failed validation.

For example, if our name value was say 28 characters, longer than the valid 20 characters,

formGroup.get("name").errors

would return:

{
    maxLength: {
        actualLength: 28,
        requiredLength: 20
    }
}

If we need something a little extra, something outside the typical min, max, required or email, we can write a custom validator.

Suppose we wanted to validate a favorite movie field. Let’s add a movie validator and determined that any value other than Back To The Future is invalid:

function movie(control: AbstractControl) : { [key: string]: any } { if (control.value !== "Back To The Future") { return { movie: { suppliedMovie: control.value, quality: "Questionable" } }; } return undefined; }

[ read more ]