AngularJS directive to focus in an input field: why is the call to setTimeout needed to make it work?

Issue

I have defined an angularjs directive, whose purpose is automatically triggering the focus on an input HTML element.

The code for the directive is the following:

function autoFocus() {
    return {
        restrict: 'A',
        scope: false,
        link: function ($scope, $element, $attrs) {
            $scope.$watch($attrs.autoFocus, function(newValue, oldValue) {
                if (!newValue) {
                    return;
                }

                const element = $element[0];
                setTimeout(function() {
                    element.focus();
                }, 0);
            });
        }
    };
}

angular
    .module('app')
    .directive('autoFocus', autoFocus);

This is an example of usage:

<input 
      ng-show="isEditMode" 
      ng-model="item.title"
      ng-blur="todo.updateTodo(item, $index); isEditMode = false;"
      auto-focus="isEditMode">

If I remove the call to setTimeout from the callback code the directive does not work as expected (the focus event is not triggered as I would expect).

Can anyone explain me why the call to setTimeout is needed in order to make it work ?

Solution

This is a common directive problem, link function runs before the DOM has finished rendering, so the element has not yet a value. The simplest (and probably cleanest) solution is the usage of $timeout that triggers a new digest cycle and ensures that the DOM has rendered.

(You should replace setTimeout with angular’s $timeout service)

Answered By – Bill P

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published