Validating Angular Reactive Forms: Part 2, Custom Validators

Rosie
4 min readJun 4, 2020

--

Just a custom flower, standing out from the others

In Part 1 of Validating Angular Reactive Forms, I covered built-in validators in Angular, which really does cover most use cases. However, just like many scenarios in development, there are exceptions where we’ve got to create our own custom code. That’s where knowing how to create custom validators comes in handy.

Custom Validator Functions

At first glance, custom validation looks kind of intimidating, since custom validators must implement the ValidatorFn interface below. Let’s break it down.

A validator is a function that takes in a generic control of type AbstractControl, which is the parent class to the three @angular/forms building blocks — FormControl, FormGroup, and FormArray. So basically, any kind of control can be validated. This function returns either a ValidationErrors error map if it’s invalid, and null if it’s valid.

The ValidationErrors type defines an error map with a key/value pair. For example, if you wanted to define a custom error called wrongFormat, you could define an error map like below. We assign it a value of true to indicate that this wrongFormat error has been set on the passed in control.

Bringing it all together, let’s create our own custom validator that checks an email control for a “.edu” top-level domain in order to get a student discount. If the user doesn’t enter a “.edu” email, the control will be marked as invalid, and we’ll return an error map with an error called nonEduEmail.

For reuse throughout our app, we created a separate file called custom-validators.ts that contains the following CustomValidators class with our first custom validator called eduEmailValidator. Back in the component, we’ll import CustomValidators, then add the new custom validator to the email FormControl.

Custom Validator Functions with Dependencies

If we want to make our custom validators more generic, we can pass parameters in. This could be helpful if you have data coming in from an API or elsewhere that will define a control’s validation status. To take a step with our existing example, we want a new custom validator that passes in any domain, rather than just a hardcoded “.edu”.

Remember up above when we covered the ValidatorFn interface, and how it only takes one parameter, an AbstractControl? Because of this, we’ll have to create a factory function to be able to pass parameters to a validator. This in turn will return an anonymous ValidatorFn. See the haveDomainValidator below to view this in action.

In the component, we’ll add the haveDomainValidator to the anotherEmail FormControl. Now we can pass in any top-level domain we’d like to validate on!

Great, we’ve covered two important cases of custom validation — creating basic custom validator functions and custom validators with dependencies. If you want to see the full demo, find it on Stackblitz.

Paired with built-in validators from Part 1, we’re able to validate Angular Reactive Forms for the majority of use cases. And if you want to learn more about Reactive Forms as a whole, check out my full course on Thinkster! We’ll walk through hands-on exercises and learn about cross-field validation as well. Thanks for reading!

--

--