Angular reactive forms and custom validations5 min read

When using reactive forms in Angular we usually avoid template based validation like required, maxlength and so on. Instead we use the Validators in the @angular/forms like this:

Note: in the above code, fb is an instance of FormBuilder which is injected into the constructor.

However, sometimes we want to implement a custom logic for our validations. Scenarios like checking a property value based on another property or checking whether two entered email addresses are equal.


We will take the email address scenario here as our base example and implement a custom validator that checks whether or not they are the same. First let’s see how the template looks like:

As you can see, it is a pretty simple form with three fields: name, email and its confirmation. Now let’s create the form for this template:

So in our model we have a name which is required, an email address and its confirmation which are required as well. However we cannot access confirm control value here so we will need another way for the confirmation validation.

That’s when the second parameter to group method on FormBuilder comes to play. It takes a function which can be executed when the values are changed. In this case we are expecting a form group as input and we are calling a private method from our component and pass that form group as input to that method.

Now let’s implement the validateEmailConfirmation method:

First we get the email and confirm controls by calling the get method on the form group. Then we check that both of them do exists by a truthy check. If either of them do not exists we just return null. Returning null means that the result is valid (remember that we have required all of them so that wouldn’t be a problem).

At last we compare the two values and if they are not equal we return an object which has a key and a boolean value assigned to it.

Binding the template to the form

We can now bind the form to the template and the validation messages to it:

The first thing we have modified in the template is [formGroup] to the form and assigned the form group we made to it. Then we added formControlName to each one of the inputs.

So far we are wired up. Then we disabled the submit button if the form is invalid. And when it comes to error messages we get the control from the form and check for error messages with normal validation e.g. required.

We need one more error message for when the two email address do not match and because we are using a custom validator we will need to check for errors on the form group rather than the controls. Note that we are just checking for user.hasError('confirm') to see whether they are equal or not.

And that’s it. We now have a working form with all the bindings and validations in place.

Hope this helps to code better and do not forget to spread the love 🙂

Users who have LIKED this post:

  • avatar
Spread the love

Leave a Reply