Reputation: 351
See EDITS below for most relevant new information.
Within an angular directive, I have an element that is a div. I am searching for descendents that are inputs and grabbing the first one to apply focus to.
var nodes = element[0].querySelectorAll('input, button');
I can access the input I want with nodes[0] but I can not figure out how to execute focus() call against it.
nodes[0].focus() does not work
$(nodes[0]).focus() does not work
angular.element(nodes[0]) does not work
When I print the nodelist to the console:
NodeList [ <button.yes.btn.btn-default>, <button.no.btn.btn-default> ]
When I select nodes[0] and print to console:
<button data-ng-click="showMismatchWarning = false; verifyRentalItemsMatch()" class="yes btn btn-default" type="button" answer="">
For example, that's the button I would want to apply focus() to. I just can't seem to figure out how to go from the queryselector result to executing the native html focus()
EDIT (MOST RELEVANT INFO):
Further information. I have different tabs so they're hidden. But the directive is applied on the same boolean expression isPage(x) so the DOM elements should be visible by this point in time.
<div ng-show="isPage(1)" myFocus="isPage(1)">
<input> <--- this very first one focus() seems to work
</div>
<div ng-show=isPage(2)" myFocus="isPage(2)">
<input> <--- this one the focus() never works
</div>
Thinking about this more it must be that the focus() is running before the DOM element is fully visible, that's why the focus() is failing. But the directive is $watching on the attributes and watches for this same expression to become true, why would it be executing before ng-show?
Here's my directive for reference.
"use strict";
angular.module('something').directive("myfocus", function() {
return {
link: function(scope, element, attributes) {
scope.$watch(attributes.focuson, function(newValue) {
if(newValue) {
highlightAndFocus(element[0]);
}
},true);
function highlightAndFocus(node) {
var task = $(node);
task.focus();
task.addClass('highlight');
var nextInput = node.querySelector('input, button:not(#cancel)');
nextInput.focus();
console.log(nextInput);
}
}
};
});
Upvotes: 3
Views: 3770
Reputation: 14123
The element to focus is apparently not visible at the moment of calling focus()
. Use a non-zero timeout to delay focusing or a built-in feature (if it exists) of the framework to detect the moment the element gets visible.
Alternatively, try to read the offsetWidth
(or offsetHeight
) property of the element to focus, to force page reflow/repaint before setting focus.
Upvotes: 1