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