Angular 2 Forms — Create Async Validator Directive

Netanel Basal
Netanel Basal
Published in
3 min readOct 24, 2016

--

By: Netanel Basal (Angular Expert) and Yaron Biton, misterBIT.co.il CTO

A form creates a cohesive, effective, and compelling data entry experience. An Angular form coordinates a set of data-bound user controls, tracks changes, validates input, and presents errors.

In this article, we will look at how to include an async validation in your form.

For example, inside a signup form we often need to validate with the server that the username or email are not already in use.

Let’s kick start this thing:

We start by creating a directive with the Directive decorator.

We want to be able to use this directive both in the model driven and template driven forms, so at the selector field, we define the CSS selector to be every element that has the asyncValidator attribute and the formControlName or ngModel attributes.

Next, we need to register the directive by pushing it to the global NG_ASYNC_VALIDATORS provider.

The NG_ASYNC_VALIDATORS is the providers array for asynchronous validators to be used.

We don’t want to override the provider, so we define the useExisting key.

If you are asking yourself what the hell this forwardRef is? You can read about this here but in a nutshell, you need this because in ECMASCRIPT2015 classes are not hoisted to the top, so at this point (inside the metadata definition), the class is not yet defined.

Let’s continue with creating the AsyncValidator class that need to implements the Validator interface.

The Validator interface has one required method: validate, In this case, because we are dealing with async validation the method signature is to return Promise or Observable.

Angular will call this function every time you make a change in your form field and be wait for the async function to be complete.

In the real world, we will have a server that verifies that the email is unique, but for the simplicity, we are going to fake this. Let’s start by showing the Promise way.

This code is straightforward; we are just returning a promise, and we are using the setTimeout function for faking async action.

If the validation pass we need to return null and if not we need to return an object with the error as the key.

So the only thing we need to do now is returning this promise from the validate method.

Now let’s see the Observable part, and be prepared to one gotcha!

This code is also straightforward, when the email is unique we pass the null value and when not we pass the object with the error.

So let’s try it by returning this function from the validate method:

If you try to run this code, you will see that nothing is changing, the form status stays the same no matter what you type. You can guess why?

This is happening because the observable never completes, so Angular does not know when to change the form status. So remember your observable must to complete.

You can accomplish this in many ways, for example, you can call the first() method, or if you are creating your own observable, you can call the complete method on the observer.

Tip: If you are working with observables, in this case you can leverage some useful methods here like:

Note: Having a public API that checks if an email exist in your system, required sine server-side protection, or otherwise hackers may exploit it as a vulnerability.

You can play with the code — plunker.

That’s all.

Please tap or click “︎❤” to help to promote this piece to others.

--

--

A FrontEnd Tech Lead, blogger, and open source maintainer. The founder of ngneat, husband and father.