Earlier today, I helped a colleague on a small issue. That issue was giving focus to an element in a modal once the modal is loaded.
This seems trivial, but it’s actually not entirely straight-forward due to Angular’s digest cycle.
As usual, I wanted to wrap this into a reusable directive.
Here’s what the directive looks like:
var focusOnLoad = function ($timeout) { var directive = { restrict: 'AC', link: function (scope, element) { $timeout(function () { element[0].focus(); }, 10, false); // pass false to avoid $apply / digest cycle } }; return directive; }; focusOnLoad.$inject = ['$timeout']; angular.module("myApp.directives") .directive('focusOnLoad', focusOnLoad);
There is nothing overtly special or complicated about this directive. We simply add it to an element to which we want to have focus on loading of a page/view/modal. The only thing that was tricky is that $timeout has to be used to ensure the digest cycle has run and that the element exists in the DOM. Without the $timeout, the element does not receive focus.
Here’s a working fiddle showing this directing working with a modalDialog:
I recommend using `false` as the 3rd argument to $timeout().
`js
$timeout(function () {
element[0].focus();
}, 10, false);
`
If set to false skips model dirty checking, otherwise will invoke fn within the $apply block.
Thanks for pointing that out. I hadn’t even thought about it since I generally use this directive in one-off scenarios. However, since it’s effectively just calling a JavaScript method that has no bearing on the Angular digest, it is completely unncesary to let $timeout $apply anything.