Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
502 views
in Technique[技术] by (71.8m points)

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

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...