Is it possible set the focus of an input field via a controller once data has loaded (via $resource in this case)?
The input is hidden via ng-show until the data is returned from the API but I can't find a way to set the focus on the input. I know the ng-model name of the input, and the input name which means I could do it via jQuery, but I'd rather do it if possible the AngularJS way.
I've tried a lot of directive examples on here but they all seem to be pre-1.2 ng-focus, rely on a ng-click first from a button (can't happen in my case) or just don't work.
Any tips very gratefully received.
This is a simple directive that might work for you
<input focus-on="!!myResourceData" />
.directive('focusOn',function($timeout) {
return {
restrict : 'A',
link : function($scope,$element,$attr) {
$scope.$watch($attr.focusOn,function(_focusVal) {
$timeout(function() {
_focusVal ? $element[0].focus() :
$element[0].blur();
});
});
}
}
})
I have extended the answer to work with angular's ng-show
and ng-hide
app.directive('focusOnShow', function($timeout) {
return {
restrict: 'A',
link: function($scope, $element, $attr) {
if ($attr.ngShow){
$scope.$watch($attr.ngShow, function(newValue){
if(newValue){
$timeout(function(){
$element[0].focus();
}, 0);
}
})
}
if ($attr.ngHide){
$scope.$watch($attr.ngHide, function(newValue){
if(!newValue){
$timeout(function(){
$element[0].focus();
}, 0);
}
})
}
}
};
})
All you need is to add attribute focus-on-show
<input type="text" ng-show="editing" focus-on-show />
Building on koolunix's answer, if you're only looking to focus input elements it may also be useful to find the first input element that is a child of the element with the focus-on directive.
This is useful in the case of an external library abstracting the input element with directives and templates.
.directive('focusOn', function ($timeout) {
return {
restrict: 'A',
priority: -100,
link: function ($scope, $element, $attr) {
$scope.$watch($attr.focusOn,
function (_focusVal) {
$timeout( function () {
var inputElement = $element.is('input')
? $element
: $element.find('input');
_focusVal ? inputElement.focus()
: inputElement.blur();
});
}
);
}
};
});
you have to use a timeout in your controller couse it hase to be rendered before
here is a similar example with a searchbox which is hided by default
HTML:
<input ng-show="vm.isActive" id="searchInputBox" ></input>
<input type="button" ng-click="vm.toggleActiveInactive();">
Controller:
vm.isActive=false;
vm.toggleActiveInactive=toggleActiveInactive; // vm= viewmodel
function toggleActiveInactive() {
if(vm.isActive==true){
vm.isActive=false;
}else{
vm.isActive=true;
$timeout(function(){
document.getElementById('searchBoxInput').focus()
}, 10 );
}
}