以角度方式设置元素焦点

Tia*_*nto 109 focus setfocus angularjs

在查看了如何使用angular设置焦点元素的示例后,我看到他们中的大多数使用一些变量来观察然后设置焦点,并且大多数变量为他们想要设置焦点的每个字段使用一个不同的变量.在一个具有大量字段的表单中,这意味着存在许多不同的变量.

考虑到jquery的方式,但是想要以有角度的方式做到这一点,我做了一个解决方案,我们使用元素的id设置焦点在任何函数中,所以,因为我是一个非常新的角度,我想得到一些意见,如果这种方式是正确的,有问题,无论如何,任何可以帮助我做到这一点的角度更好的方式.

基本上,我创建了一个指令,用于监视用户使用指令或默认的focusElement定义的作用域值,并且当该值与元素的id相同时,该元素集自身焦点.

angular.module('appnamehere')
  .directive('myFocus', function () {
    return {
      restrict: 'A',
      link: function postLink(scope, element, attrs) {
        if (attrs.myFocus == "") {
          attrs.myFocus = "focusElement";
        }
        scope.$watch(attrs.myFocus, function(value) {
          if(value == attrs.id) {
            element[0].focus();
          }
        });
        element.on("blur", function() {
          scope[attrs.myFocus] = "";
          scope.$apply();
        })        
      }
    };
  });
Run Code Online (Sandbox Code Playgroud)

由于某种原因需要获得焦点的输入将采用这种方式

<input my-focus id="input1" type="text" />
Run Code Online (Sandbox Code Playgroud)

这里设置焦点的任何元素:

<a href="" ng-click="clickButton()" >Set focus</a>
Run Code Online (Sandbox Code Playgroud)

以及设置焦点的示例函数:

$scope.clickButton = function() {
    $scope.focusElement = "input1";
}
Run Code Online (Sandbox Code Playgroud)

这是角度很好的解决方案吗?是否有问题,由于我的经验不佳,我还没有看到?

rye*_*lar 173

您的解决方案的问题在于,当绑定到创建新范围的其他指令时,它不能很好地工作,例如ng-repeat.更好的解决方案是简单地创建一个服务函数,使您能够在控制器中强制关注元素,或者在html中以声明方式聚焦元素.

DEMO

JAVASCRIPT

服务

 .factory('focus', function($timeout, $window) {
    return function(id) {
      // timeout makes sure that it is invoked after any other event has been triggered.
      // e.g. click events that need to run before the focus or
      // inputs elements that are in a disabled state but are enabled when those events
      // are triggered.
      $timeout(function() {
        var element = $window.document.getElementById(id);
        if(element)
          element.focus();
      });
    };
  });
Run Code Online (Sandbox Code Playgroud)

指示

  .directive('eventFocus', function(focus) {
    return function(scope, elem, attr) {
      elem.on(attr.eventFocus, function() {
        focus(attr.eventFocusId);
      });

      // Removes bound events in the element itself
      // when the scope is destroyed
      scope.$on('$destroy', function() {
        elem.off(attr.eventFocus);
      });
    };
  });
Run Code Online (Sandbox Code Playgroud)

调节器

.controller('Ctrl', function($scope, focus) {
    $scope.doSomething = function() {
      // do something awesome
      focus('email');
    };
  });
Run Code Online (Sandbox Code Playgroud)

HTML

<input type="email" id="email" class="form-control">
<button event-focus="click" event-focus-id="email">Declarative Focus</button>
<button ng-click="doSomething()">Imperative Focus</button>
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!对于那些想知道角度文档中引用它的人,这里是[link](https://docs.angularjs.org/error/$rootScope/inprog)(带我永远找到) (3认同)
  • 为了集中输入,角度所需的工作量是疯狂的. (3认同)

Bra*_*lio 19

关于这个解决方案,我们可以创建一个指令并将其附加到DOM元素,该元素必须在满足给定条件时获得焦点.通过遵循这种方法,我们避免将控制器耦合到DOM元素ID.

示例代码指令:

gbndirectives.directive('focusOnCondition', ['$timeout',
    function ($timeout) {
        var checkDirectivePrerequisites = function (attrs) {
          if (!attrs.focusOnCondition && attrs.focusOnCondition != "") {
                throw "FocusOnCondition missing attribute to evaluate";
          }
        }

        return {            
            restrict: "A",
            link: function (scope, element, attrs, ctrls) {
                checkDirectivePrerequisites(attrs);

                scope.$watch(attrs.focusOnCondition, function (currentValue, lastValue) {
                    if(currentValue == true) {
                        $timeout(function () {                                                
                            element.focus();
                        });
                    }
                });
            }
        };
    }
]);
Run Code Online (Sandbox Code Playgroud)

可能的用法

.controller('Ctrl', function($scope) {
   $scope.myCondition = false;
   // you can just add this to a radiobutton click value
   // or just watch for a value to change...
   $scope.doSomething = function(newMyConditionValue) {
       // do something awesome
       $scope.myCondition = newMyConditionValue;
  };
Run Code Online (Sandbox Code Playgroud)

});

HTML

<input focus-on-condition="myCondition">
Run Code Online (Sandbox Code Playgroud)


cst*_*lan 11

我希望尽可能避免使用DOM查找,监视和全局发射器,因此我使用更直接的方法.使用指令分配一个专注于指令元素的简单函数.然后在控制器范围内的任何需要的地方调用该函数.

这是将其附加到范围的简化方法.请参阅完整代码段以处理controller-as语法.

指示:

app.directive('inputFocusFunction', function () {
    'use strict';
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            scope[attr.inputFocusFunction] = function () {
                element[0].focus();
            };
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

并在HTML中:

<input input-focus-function="focusOnSaveInput" ng-model="saveName">
<button ng-click="focusOnSaveInput()">Focus</button>
Run Code Online (Sandbox Code Playgroud)

或在控制器中:

$scope.focusOnSaveInput();
Run Code Online (Sandbox Code Playgroud)

angular.module('app', [])
  .directive('inputFocusFunction', function() {
    'use strict';
    return {
      restrict: 'A',
      link: function(scope, element, attr) {
        // Parse the attribute to accomodate assignment to an object
        var parseObj = attr.inputFocusFunction.split('.');
        var attachTo = scope;
        for (var i = 0; i < parseObj.length - 1; i++) {
          attachTo = attachTo[parseObj[i]];
        }
        // assign it to a function that focuses on the decorated element
        attachTo[parseObj[parseObj.length - 1]] = function() {
          element[0].focus();
        };
      }
    };
  })
  .controller('main', function() {});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>

<body ng-app="app" ng-controller="main as vm">
  <input input-focus-function="vm.focusOnSaveInput" ng-model="saveName">
  <button ng-click="vm.focusOnSaveInput()">Focus</button>
</body>
Run Code Online (Sandbox Code Playgroud)

编辑提供有关此方法的原因的更多说明,并扩展用于控制器的代码片段.


小智 9

你可以试试

angular.element('#<elementId>').focus();
Run Code Online (Sandbox Code Playgroud)

例如.

angular.element('#txtUserId').focus();
Run Code Online (Sandbox Code Playgroud)

它为我工作.

  • 注意:这只适用于使用完整的jQuery而不是依赖于Angular中嵌入的jqLit​​e.请参阅https://docs.angularjs.org/api/ng/function/angular.element (4认同)
  • 这是jQuery这样做的方式,而不是一种有角度的方式.问题特别要求如何以有角度的方式做到这一点. (3认同)