Setting focus on an input field after ng-show

2019-01-22 02:33发布

问题:

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.

回答1:

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();
                });
            });
        }
    }
})


回答2:

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 />


回答3:

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();
                    });
                }
            );

        }
    };
});


回答4:

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

          }
        }