akonsu
akonsu

Reputation: 29538

set focus to textarea in an angular directive

I have a directive that implements in-place editing. In its link function I have a watch that is supposed to set focus on the text box when editing is switched on:

$scope.$watch('view.enabled', function(value) {
  if (value) {
    var element = $element.find('input') || $element.find('textarea');
    var input = element && element[0];
    if (input) {
      $timeout(function() {
        input.focus()
      });
    }
  }
});

the directive can instantiate either an input element, or a textarea depending on the parameters. The problem is that invoking focus() on the textarea element does not set focus to it. For input elements it does set the focus though.

Here is plnkr. Please help.

Plunker Link

EDIT: using autofocus attribute on the textarea in HTML makes it get the focus, but I still do not understand why I cannot do it programmatically.

Upvotes: 2

Views: 7712

Answers (2)

Cody Moniz
Cody Moniz

Reputation: 5065

I don't think $timeout is a good way to focus the element on creation. You can split the "link" attribute can be split into "pre" and "post", for pre-link and post-link functions.

Working Example: http://plnkr.co/edit/Fj59GB

// this is the directive you add to any element you want to highlight after creation
Guest.directive('autoFocus', function() {
    return {
        link: {
            pre: function preLink(scope, element, attr) {
                console.debug('prelink called');
                // this fails since the element hasn't rendered
                //element[0].focus();
            },
            post: function postLink(scope, element, attr) {
                console.debug('postlink called');
                // this succeeds since the element has been rendered
                element[0].focus();
            }
        }
    }
});
<input value="hello" />
<!-- this input automatically gets focus on creation -->
<input value="world" auto-focus />

Full AngularJS Directive Docs: https://docs.angularjs.org/api/ng/service/$compile

Upvotes: 2

user13500
user13500

Reputation: 3856

You do not set focus to the textarea. Try this:

if (input) {
    $timeout(function() {
        console.log(input);
        input.focus();
    });
}

It will give you this:

<input ng-show="editableType !== 'multi-line'" 
       ng-model="view.value" 
       class="ng-pristine ng-valid ng-hide">

and not the textarea. Quick fix (for textarea only) could be:

var element = $element.find('textarea');

Depending on order of things, I'm not sure if this would help:

var element = $element.find('textarea') || $element.find('input');

have to look closer at it ...

Upvotes: 1

Related Questions