Yet another approach to form control’s error messages in Angular

Wojciech Trawiński
Dec 3, 2019 · 3 min read

I’ve recently heard an interesting requirement, namely that a form control’s error message should be visible once a user has interacted with it (either it’s touched or dirty), however the control should be treated as dirty ⚫️ when a given period of time has elapsed since a user stopped typing for the first time. In short, old good check: isInvalid and isDirty or isTouched would do the job if it wasn’t for the additional time-based requirement. In this blog post I will show you how to accomplish the goal with the aid of Angular directives, dependency injection and RxJS.

This blog post is inspired by Netanel Basal who makes a form control’s error messages appear magically, check it out ◀️.


Make control pristine again!

In fact, it’s all about cheating Angular that a form control is pristine even though it reports that it’s dirty. You need to keep lying until the required amount of time has passed and then stop cheating to Angular. Use the following code to take over control 👑:

You simply subscribe to the control’s valueChanges stream and pretend that typing into it should not be treated as making the control dirty unless a given number of milliseconds (argument of the debounceTime operator) has passed.

Note that setting a value imperatively with the aid of the setValue method results in a next notification in the valueChanges stream as well (by default). Therefore, if you would like this feature to work in such scenario as well, you need to either set the emitEvent option to false (as the second argument of the setValue method) or skip the first emitted value.

Let’s think where to put the above code in Angular application ❓


Common logic in directives

I believe that it’s best to put the required logic in a reusable directive. You can narrow the number of affected form controls with the aid of custom selector as I did in the following example. However, if you wish to apply the behavior to the entire app, you can pick a more general selector which affects all form controls. Let’s take a look at the code 👀:

The directive gets an instance of NgControl which enables to retrieve an underlying FormControl object. In addition, you need to remember to unsubscribe in order to get rid of memory leaks, since a component may get destroyed without filling the form it contains.


Example

The only thing you need to is to apply the directive’s selector to the desired controls:

Feel free to play around with the entire example:


Conclusions

In this blog post I presented how to delay marking a form control as dirty with the aid of RxJS, dependency injection and directives. It’s good to have such stuff 🔨 in your toolbelt when you need to face some challenging problems in your Angular applications.

I hope you liked the post and learned something new 👍 If so, please give me some applause 👏

JavaScript everyday

Wojciech Trawiński

Written by

Doing awesome things using JavaScript

JavaScript everyday

Improve your JavaScript skills everyday!

More From Medium

More on Angular from JavaScript everyday

More on Angular from JavaScript everyday

Managing date formats in Angular apps

More on Rxjs from JavaScript everyday

More on Typescript from JavaScript everyday

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade