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.
When it comes to do DOM manipulation, binding event, etc... It happens, that we define functions that manipulates the DOM in a custom directive's link function, but we call it from the controller (we define functions in the $scope so it can be accessible by the given controller).
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With