I need a <div>
with a text <input>
to be toggled visible and then focus on the text element.
Pressing a button sets two conditions to true, one to show the parent element, and another to focus the input element.
I'm using two custom directives:
- The ng-visible directive toggles the visibility property (visible / hidden) when evaluated truthful.
- The ng-focus directive focuses the element when evaluated truthful.
The problem I ran into is my directive tries to focus the element too soon (before the block has had enough time to display as visibility: visible) and thus the focusing fails. Quick test reveals if a 1 second long $timeout delay is added, it works fine.
How can I ensure the focus directive waits until its visible before trying to focus the element?
Minor note: I am aware of ng-show / ng-hide (which works in my testing), but I need to use the CSS visibility property here instead.
HTML
<button ng-click="showMe = true; focusMe = true;"></button>
<div ng-visible="showMe">
<input type="text" ng-focus="focusMe"/>
</div>
Visibility Directive
app.directive('ngVisible', function($animate) {
return {
restrict: 'A',
multiElement: true,
link: function(scope, element, attr) {
scope.$watch(attr.ngVisible, function(value) {
if( value === true ) {
$animate.addClass(element, 'visible', function() {
$animate.removeClass(element, 'invisible', function() {
scope.$apply();
});
});
} else {
$animate.addClass(element, 'invisible', function() {
$animate.removeClass(element, 'visible', function() {
scope.$apply();
});
});
}
});
}
}
});
Focus Directive
app.directive('ngFocus', function($timeout, $parse) {
return {
link: function(scope, element, attr) {
var model = $parse(attr.ngFocus);
scope.$watch(model, function(value) {
if(value === true) {
$timeout(function() {
element[0].focus();
});
}
});
// Set attr value to false on blur event so it can be refocused
element.bind('blur', function() {
scope.$apply(model.assign(scope, false));
});
}
};
});
Aucun commentaire:
Enregistrer un commentaire