关于angularjs:输入自动对焦属性

Input autofocus attribute

我的代码中有地方,我有这个:

1
<input data-ng-disabled="SOME_SCOPE_VARIABLE" />

我也希望能够像这样使用它:

1
<input data-ng-autofocus="SOME_SCOPE_VARIABLE" />

甚至更好,模仿ng-style的完成方式:

1
<input data-ng-attribute="{autofocus: SOME_SCOPE_VARIABLE}" />

当前版本的AngularJS中是否存在这种情况? 我注意到代码中有一个BOOLEAN_ATTR,它获取AngularJS支持的所有attr。 我不想修改它,因为害怕更改版本而忘记更新。


更新:AngularJS现在有一个ngFocus指令,用于计算焦点上的表达式,但为了完整起见,我在这里提到它。

当前版本的AngularJS没有焦点指令,但它在路线图中。巧合的是,我们昨天在邮件列表上谈到了这一点,我想出了这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
angular.module('ng').directive('ngFocus', function($timeout) {
    return {
        link: function ( scope, element, attrs ) {
            scope.$watch( attrs.ngFocus, function ( val ) {
                if ( angular.isDefined( val ) && val ) {
                    $timeout( function () { element[0].focus(); } );
                }
            }, true);

            element.bind('blur', function () {
                if ( angular.isDefined( attrs.ngFocusLost ) ) {
                    scope.$apply( attrs.ngFocusLost );

                }
            });
        }
    };
});

这可以按照您的要求处理范围变量:

1
<input type="text" ng-focus="isFocused" ng-focus-lost="loseFocus()">

这是一个小提琴:http://jsfiddle.net/ANfJZ/39/


您可以使用内置的ngAttr属性绑定来完成此操作。

1
<input ng-attr-autofocus="{{SOME_SCOPE_VARIABLE}}">

如果定义了SOME_SCOPE_VARIABLE(即使它是false),则会添加自动聚焦属性,如果undefined,则会删除该属性。所以我强迫假值为undefined

1
$scope.SOME_SCOPE_VARIABLE = someVar || undefined;


这个指令应该做的伎俩:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
angular.module('utils.autofocus', [])
.directive('autofocus', ['$timeout', function($timeout) {
  return {
    restrict: 'A',
    scope: {'autofocus':'='}
    link : function($scope, $element) {
      $scope.$watch 'autofocus', function(focus){
        if(focus){
          $timeout(function() {
            $element[0].focus();
          });
        }
      }
    }
  }
}]);

取自这里:https://gist.github.com/mlynch/dd407b93ed288d499778


1
2
3
4
5
scope.doFocus = function () {
                $timeout(function () {
                        document.getElementById('you_input_id').focus();
                    });
            };


所以没有$ timeout你也可以像这样使用自动对焦 -

1
2
3
4
    <input type="text" ng-show="{{condition}}" class='input-class'></input>
    angular.element(document).ready(function(){
    angular.element('.input-class')[0].focus();
    });

创建这样的指令

1
2
3
4
5
6
7
8
9
10
11
12
13
.directive('autoFocus', ['$timeout', function ($timeout) {
        return {
            restrict: 'A',
            link: function ($scope, $element) {
                $timeout(function () {
                    $element[0].focus();
                });
            }
        }



<input type="text" auto-focus class="form-control msd-elastic" placeholder="">


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js">
<body>

 
 
     <input ng-attr-focus={{$first}} value="{{x.name + ', ' + x.country }}" />
 




        var myApp = angular.module('myApp', []);
        myApp.controller('namesCtrl', function($scope) {
    $scope.names = [
        {name:'x1',country:'y1'},
        {name:'x2',country:'y2'},
        {name:'x3',country:'y3'}
    ];
});

        myApp.directive("focus", function(){
            return {
                restrict:"A",
                link: function link(scope, element, attrs) {

                      if(JSON.parse(attrs.focus)){
                          element[0].focus();
                      }
                }
            };
        });

</body>
</html>

为我的一个用例创建了上面的自定义指令。

  • 始终专注于第一个输入元素。
  • 适用于ajax数据,浏览器后退/前进按钮。
  • 在chrome和firefox上测试(此处不支持默认自动对焦)

JSON.parse用于将从html返回的字符串"true"解析为JS中的布尔值true。
对于if条件,使用attrs.focus ==="true"的另一种方法。


我用两个自定义指令做了这个,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
(function(angular) {
  'use strict';

  /* @ngInject */
  function myAutoFocus($timeout) {
    return {
      restrict: 'A',
      link: function(scope, element) {
        $timeout(function() {
          element[0].focus();
        }, 300);
      }
    };
  }

  function myFocusable() {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        var focusMethodName = attrs.myFocusable;
        scope[focusMethodName] = function() {
          element[0].focus();
        };
      }
    };
  }

  angular
    .module('myFocusUtils', [])
    .directive('myAutoFocus', myAutoFocus)
    .directive('myFocusable', myFocusable);

}(angular));

如果将属性my-auto-focus添加到元素,它将在300ms后获得焦点。我将值设置为300而不是0,以便在设置焦点之前加载其他异步组件。

属性my-focusable将在当前范围内创建一个函数。调用时,此函数将焦点设置为元素。因为它在范围内创造了某些东西,所以要小心避免覆盖某些东西。

这样您就不需要向Angular的摘要周期(watch)添加内容,并且可以在视图中完全执行:

1
2
<input my-focusable="focusOnInput"></input>        
<button ng-click="focusOnInput()">Click to focus</button>

我创建了一个JSFiddle来显示myFocusable指令:http://jsfiddle.net/8shLj3jc/

由于某些原因我不知道,myAutoFocus指令在JSFiddle中不起作用,但它在我的页面中有效。


我所做的是在输入上使用常规自动对焦:

然后,当角度准备就绪时,我将焦点设置在第一个可见光输入的自动对焦上:

1
2
3
angular.element(document).ready(function() {
  $('input[autofocus]:visible:first').focus();
});

希望这可以帮助。