Custom validation for your reactive forms?

nishugoel profile image Nishu Goel Updated on ・2 min read

When working with forms in Angular, we are provided with a choice. The choice is similar to the one between choosing tea or coffee. This choice is about choosing which types of forms we should use as per the requirement of our solution.
And the two options that we get are:

  • Template-driven forms
  • Model-driven forms a.k.a Reactive Forms

Now each of these have their own advantage over another and it totally depends on the developer that which one he prefers to use for this set of requirement. Is he looking to quickly get an input from the user without much interest in all the fancy validation and stuff OR is she wanting to leverage all the possibilities that a form is capable of providing.
One of the reasons somebody would choose to work with template-driven forms can be to get the work done without really wanting to have a form model inside the component, leaving alone the unit testing bit which gets difficult to do against the DOM.

One of the reasons somebody would choose to work with model-driven forms (Reactive forms) can be to do most of the task from the component class only putting the instances of the input fields on the template, making it easier to unit test and use up other great features of reactive forms, for example, Custom validation.

In this blog post, we will see how we can use custom validation inside our forms and make the best use of reactive forms.
Now a validator is nothing but a function. To create this validator fucntion, the syntax goes like this:

function classValidator(control: AbstractControl) : {[key : string] : boolean} | null {
return null;

Let us break this down now and understand.
Since our custom validator is a function, we use the function keyword followed by the name of our validator that we want to create. As an argument comes the FormControl or FormGroup for which use the base class i.e., AbstractControl. The next part in it means what type of value will be returned by the function. So it there is something wrong with the input field, it returns an object in the form of a key-value pair, where the value is of type boolean and the key is of type string. If everything works fine with the input field, it returns null.
So lets create a simple range validator for age here:

function ageValidator (control: AbstractControl):{[key: string]: boolean} | null {
if( control.value !==null && (isNaN(control.value) || control.value <20 || control.value> 70)){
return {'ageValidator': true}
return null;

To apply this to your input field, use the name of your custom validator on the form control name inside the form group,

this.customerForm = this.fb.group({
firstname: ['', [Validators.required, Validators.minLength(5)]],
email: ['', Validators.required],
age: [null, ageValidator]

On the template,

<span *ngIf= “customerForm.get(‘age’).errors?.ageValidator”>Only for age group 20 to 70</span>

Let us look at the results in the browser now.

Read more here: https://nishugoel.wordpress.com/2019/07/27/custom-validation-for-your-reactive-forms/


Editor guide
cubiclebuddha profile image
Cubicle Buddha

Fascinating topic. Thank you for writing about TypeScript which is a language that I really love working in). I wanted to let you know that in the dev.to editor, you can wrap your code samples in three backtick characters to make it show up as code instead of just text. You can also add the language right after the three backticks to get it to do syntax highlighting.

nishugoel profile image
manohar719 profile image

Thank you Goel, it helped me !!!