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.
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.
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.
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.