Easy dom manipulation in AngularJS - click a button, then set focus to an input element

angularjs, javascript, jquery

Solution

DOM manipulation should be in a directive instead of the controller. I would define a `focusInput` directive and use it on the button:

<div class="button" focus-input>{{element.name}}</div>   

Directive:

app.directive('focusInput', function($timeout) {
  return {
    link: function(scope, element, attrs) {
      element.bind('click', function() {
        $timeout(function() {
          element.parent().parent().find('input')[0].focus();
        });
      });
    }
  };
});

Plunker

Since jqLite is rather limited in terms of DOM traversal methods, I had to use `parent().parent()`. You may wish to use jQuery or some JavaScript methods.

As you already found out, `$timeout` is needed so that the `focus()` method is called after the browser renders (i.e., finishes handling the click event).

`find('input')[0]` gives us access to the DOM element, allowing us to use the JavaScript `focus()` method (rather than `find('input').focus()` which would require jQuery).

Problem

I have this angular code: ``` <div class="element-wrapper" ng-repeat="element in elements"> <div class="first-wrapper"> <div class="button" ng-click="doSomething(element,$event)">{{element.name}}</div> </div> <div class="second-wrapper"> <input type="text" value="{{element.value}}"> </div> </div> ``` What I want to happen: when the user clicks the button - the input element will be focused. How do I find the input element after I click the button element and focus it? I can do a function that looks like this: ``` function doSomething(element,$event) { //option A - start manipulating in the dark: $event.srcElement.parentNode.childNodes[1] //option B - wrapping it with jQuery: $($event.srcElement).closest('.element-wrapper').find('input').focus(); } ``` Neither of them work - Is there a nicer Angular way to do it? Using functions such as `.closest()` and `.find()` as in jQuery? Update: I found this hack to be working (but it still doesn't seem like the correct solution): ``` function doSomething(element,$event) { setTimeout(function(){ $($event.srcElement).closest('.element-wrapper').find('input').focus(); },0) } ``` I am wrapping it with setTimeout so after Angular finishes all of its manipulations it focuses on the input element.

Original source