Monday, August 12, 2013

AngularJS Missing Directives: Focus & Blur

After my last post discussing the missing native form reset directive, I was asked what other missing directives there might be. Which is a great question. AngularJS provides so many great directives out of the box, what could it possibly be missing?

Well, lets start with simple user input events. AngularJS 1.1.5 supports the following events as ng-directives:
* There is of course also ng-submit, which was mentioned in the last post.

While that list is pretty extensive there are two glaring omissions, namely blur and focus events. Luckily these can be easily added as you will see below.

Since there is nothing uniquely special about these two events compared to the list above, we can use the AngularJS source code as a template for adding two directives to support these events. The bonus for doing that is extrapolating and slightly modifying the code for our goals is quick and painless. Lesson to be learned: always look to the source for tips and guidance.

First, a note discussing this approach. I have read various development threads discussing how a focus and/or a blur directive should work. The main debate seems to boil down to a disagreement between essentially adverbs. Specifically 'on' and 'while'. The latter assigns a state indicator that can be monitored to determine if an element is currently blurred or focused. The former, which is the approach the following example will use, follows the native browser event listeners for firing when an event occurs.

Got it? Good. Lets jump in then. Click on the input element to give it focus and then click outside of it to blur it.



It works, but how? Focusing on the HTML tab we can see the directives are simply passing an AngularJS expression that sets the scope variable focused to either true or false if the input element is focused or blurred respectively.



Looking at the directive code on the JavaScript tab, the first thing you will notice is rather than repeating identical code for each directive I use an angular.forEach to loop through both events and dynamically create a directive for each one.



Again, there is nothing very special about the code in this directive. In fact anything of interest was discussed in the last post (review here if you need to). Basically the directive will evaluate whatever the AngularJS expression is when the event fires.

NOTE: If you want to do something only when an element has focus (or blurred) you would need to use both directives to monitor the element as this example does.

UPDATE (2013-08-13): AngularJS 1.2.0rc1 now includes blur and focus events! Wooohoooo! Check out the follow-up post to see how it compares.

UPDATE (2013-8-26): Part 2 - Supporting the 'while' adverb through a directive.