2

I have an html button like so:

<button autofocus role="button" ng-disabled="something.$invalid">{{ Continue }}</button>

The button is initially disabled so the autofocus attribute doesn't have any effect. What I want to happen is when the button does get enabled, I want the focus on the button right away.

How can I accomplish this?

edit: As stated below, a directive to watch for a value then set focus to the element is one way to solve this. I've tried to create the same directives as below but focus doesn't seem to be getting set.

user3667725
  • 111
  • 1
  • 9
  • 1
    possible duplicate of [JavaScript set focus to HTML form element](http://stackoverflow.com/questions/17500704/javascript-set-focus-to-html-form-element) – vol7ron Apr 21 '15 at 01:49
  • are you looking for something like `ng-focus`? – batmaniac7 Apr 21 '15 at 02:00
  • IIRC, ng-focus evaluates an expression when the element comes into focus, so i'm not really looking for that. I have a form in which a user cannot continue until the form is $valid. So, the continue button should not work until $valid is true. In other words, once something.$valid is true, the button should auto focus so that the user can just hit the enter or space bar to "continue" without having to click with the mouse. – user3667725 Apr 21 '15 at 19:03

3 Answers3

1

As it was mentioned in the comment a directive would be good for this. The following will watch the model and passed to it and focus on the element when it becomes true.

module.directive('focusToMe', function($parse) {
    return {
        restrict: 'A',
        compile: function() {
            var directiveName = this.name;

            return function(scope, element, attrs) {
                scope.$watch(attrs[directiveName], function(newVal, oldVal) {
                    if (newVal) {
                        element.focus();
                    }
                })
            }
        }
    }
});

You would then add it to your button element:

<button autofocus role="button" ng-disabled="something.$invalid" focus-to-me="something.$invalid">{{ Continue }}</button>
Enzey
  • 5,254
  • 1
  • 18
  • 20
  • I tried doing it this way but still no luck. when i log out attrs[directiveName], i just get the string that's being passed to focus-to-me. For example: focus-to-me="something.$invalid"..... when i console log out attrs[directiveName], i get "something.$invalid". its not evaluated – user3667725 Apr 21 '15 at 18:58
  • Also im getting element.focus is not a function error. I believe it should be elemtn[0].focus() but this doesn't get the button focused either but does get rid of the error. – user3667725 Apr 21 '15 at 19:27
0

The following directive controls the focus of an element to which it is applied:

.directive('focusOn', function() {
    return function(scope, elem, attrs) {
        scope.$watch(function(scope) {
            return scope[attrs.focusOn];
        },
        function(val) {
            if (val) {
                elem[0].focus();
            }
        });
    };
});

Apply it to the button element like:

<button focus-on="focusMe">click-me</button>

See full example in this plunk: http://plnkr.co/edit/zrd9hl7ilTrhIKshStXR?p=preview

umarius
  • 1
  • 2
0

Ah I got it working. I had to set the focus function to fire off after one cycle of the event loop with $timeout like so:

.directive('focusToMe', function($timeout) {
        return {
            restrict: 'A',
            compile: function() {
                var directiveName = this.name;

                return function(scope, elem, attrs) {
                    scope.$watch(attrs[directiveName], function(newVal, oldVal) {
                        if (newVal) {
                            $timeout(function() {
                                elem[0].focus();
                            }, 0)
                        }
                    })
                }
            }
        }
    })
user3667725
  • 111
  • 1
  • 9