Create directive for showing error message in form with Angular

Written by Elec_crafter | Published 2017/05/25
Tech Story Tags: javascript | angular2 | typescript | angular | validation

TLDRvia the TL;DR App

Form and validation are fundamental in website. Angular provide easy way to handle validation in form but we can still simplify more validation work with directive.

In this post, I’ll show you how easily show validation error message without *ngIf and long expression.

I assume you’ve already familar with Angular, I suggest you read these topic if you don’t know them.

The problem in validation.

Showing message to the user makes our code looks ugly. For example

Before add validation message

After add validation message

Ewww. it’s so mess now. 😵

So I’m trying to get rid of duplicated code with directive magic. Here it’s what I achieve.

It does looks a lot cleaner. 😻

This is achieved by 2 directives. invalidmessage and invalidType.

InvalidmessageDirective

invalidmessage directive receive form control by name and set visible of hosted element based on the form control’s error.

Here’s the code of invalidmessage directive.

Don’t worry, I will explain code soon.

invalidmessage directive

First, I inject ControlContainer for get Formgroup instance from nearest parent’s injector (it’s myForm in the above example ).

Now we can easily get from control by name (eg,this.form.get('yourcontrolname') ). 😎

FormControl instance can get value, error and so on. Actually it’s just form control that you use in ReactiveForm. For example, this.myform.get('name');

I create setVisible() method for set hosted element visble when the control is valid and hidden when it’s not.

Showing error message at first is really bad (Many Ux website told that) so it’d make user less grumpy if it just show when user interact with control or click submit button already. I check that with this.control.dirty and this.hasSubmitted in the above .

setVisible() method will be called when value of control is changed and when user click submit button.

Notice _Observable.of_ , it’ll emit immediately so _setVisible()_ will be called at initial.

formSubmit$ is Observable that emit when form is submitted. It’ll set hasSubmitted to true.

invalidmessage provide match method for invalidType directive to call for checking if it match control’s error type.

this.control.errors is object whose propery name is error type. Say, form control has required and email validations and user break it. FormControl errors object will be like this.

{required:true,email:true}

You’ll see how it’s used in the next section.

InvalidTypeDirective

This directive is for set visible of host element based on error type of control which control difined in invalidmessage directive.

As you may notice in the above example,***invalidmessage** . There’s asterisk prefix. It’s called Stuctural directive. For short, Stuctural directive will create ng-template surrounding host element which make host element won’t be rendered until you explicitly render with ViewContainerRef

Let code explian itself

This directive is injected with 3 dependencies — InvalidmessageDirective, TemplateRef and ViewContainerRef.

TemplateRef and ViewContainerRef are for create and remove host element(which it’s error message).

Angular inject instance of InvalidmessageDirective that is nearest parent injector.

<div invalidmessage="name"><p *invalidType="'required'">Please provide name</p>

</div>

InvalidTypeDirective which is on <p> can get instance of **invalidmessageDirective (**which is on <div>) by injecing InvalidmessageDirective in invalidTypeDirective as we did above.

So invalidType directive can use property and method of invalidmessage directive instance**.**

invalidmessage’s match method take a type of error by argument(which it’s defined with type property) and check if error object has the specified error type.

If invalidmessage’s match return true, view container will create view from TemplateRef (it’s ng-template surrounding hosted element) and view container will clear when it’s false. In layman’s term, invalidType directive show and remove host element based on return value of invalidmessage’s match method.

It need to check if view container hasn’t created by checking _hasView_ property so it won’t create repeatly.

setVisible() is called when invalidmessage’s controlValue$ emit(control value change and user click submit button).

That’s all. These two directives can simplify our form validation. It’s maybe not perfect but it can give you an idea.

If you have any question or suggestion, please comment below.

Here’s plunker

Plunker_Plunker is an online community for creating, collaborating on and sharing your web development ideas._plnkr.co

If you like this post, please leave a like ❤️ and follow me on Medium or Twitter to read more about Angular, Javascript and more.


Published by HackerNoon on 2017/05/25