Angularjs 以角度方式设置元素焦点

Angularjs 以角度方式设置元素焦点,angularjs,focus,setfocus,Angularjs,Focus,Setfocus,在查找了如何使用角度设置焦点元素的示例之后,我看到大多数元素都使用一些变量来观察然后设置焦点,并且大多数元素对每个要设置焦点的字段都使用一个不同的变量。在一个有很多字段的表单中,这意味着有很多不同的变量 考虑到jquery的方式,但想以angular的方式来实现这一点,我提出了一个解决方案,我们使用元素的id在任何函数中设置焦点,因此,由于我在angular方面非常新,我想获得一些意见,如果这种方式是正确的,有问题,不管怎样,任何可以帮助我在angular方面做得更好的方法 基本上,我创建了一个

在查找了如何使用角度设置焦点元素的示例之后,我看到大多数元素都使用一些变量来观察然后设置焦点,并且大多数元素对每个要设置焦点的字段都使用一个不同的变量。在一个有很多字段的表单中,这意味着有很多不同的变量

考虑到jquery的方式,但想以angular的方式来实现这一点,我提出了一个解决方案,我们使用元素的id在任何函数中设置焦点,因此,由于我在angular方面非常新,我想获得一些意见,如果这种方式是正确的,有问题,不管怎样,任何可以帮助我在angular方面做得更好的方法

基本上,我创建了一个指令,用于观察用户使用该指令定义的范围值,或者默认值的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();
        })        
      }
    };
  });
由于某种原因需要获得焦点的输入将以这种方式进行

<input my-focus id="input1" type="text" />

这是一个很好的解决方案吗?您的解决方案是否存在一些问题,而我的经验不足,我还看不到这些问题?

您的解决方案的问题是,当与创建新范围的其他指令(例如
ng repeat
)绑定时,它无法正常工作。一个更好的解决方案是简单地创建一个服务函数,使您能够在控制器中强制聚焦元素,或者在html中声明聚焦元素

JAVASCRIPT

服务

指示

控制器

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>

陈述焦点
命令焦点

关于这个解决方案,我们可以创建一个指令并将其附加到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();
                        });
                    }
                });
            }
        };
    }
]);
可能的用法

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

HTML


我更喜欢使用表达式。这让我可以在字段有效、达到一定长度时,以及加载后,对按钮进行聚焦

<button type="button" moo-focus-expression="form.phone.$valid">
<button type="submit" moo-focus-expression="smsconfirm.length == 6">
<input type="text" moo-focus-expression="true">

在复杂形式上,这也减少了为聚焦而创建额外范围变量的需要


请参见

我喜欢尽可能避免DOM查找、监视和全局发射器,因此我使用更直接的方法。使用指令指定一个简单函数,该函数集中于指令元素。然后在控制器范围内的任何需要的地方调用该函数

下面是一种将其附加到范围的简化方法。请参阅将控制器作为语法处理的完整代码段

指令:

app.directive('inputFocusFunction', function () {
    'use strict';
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            scope[attr.inputFocusFunction] = function () {
                element[0].focus();
            };
        }
    };
});
angular.module("app").directive("focusOn", function($timeout) {
  return {
    restrict: "A",
    link: function(scope, element, attrs) {
      scope.$on(attrs.focusOn, function(e) {
        $timeout((function() {
          element[0].focus();
        }), 10);
      });
    }
  };
});
和html格式:

<input input-focus-function="focusOnSaveInput" ng-model="saveName">
<button ng-click="focusOnSaveInput()">Focus</button>
angular.module('app',[])
.directive('inputFocusFunction',function(){
"严格使用",;
返回{
限制:“A”,
链接:功能(范围、元素、属性){
//解析属性以适应对对象的赋值
var parseObj=attr.inputFocusFunction.split('.');
var attachTo=范围;
for(var i=0;i

集中
您可以试试

angular.element('#<elementId>').focus();

它对我有用。

另一个选择是使用Angular的内置发布子架构,以便通知您的指令聚焦。与其他方法类似,但它不直接绑定到属性,而是监听特定键的作用域

指令:

app.directive('inputFocusFunction', function () {
    'use strict';
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            scope[attr.inputFocusFunction] = function () {
                element[0].focus();
            };
        }
    };
});
angular.module("app").directive("focusOn", function($timeout) {
  return {
    restrict: "A",
    link: function(scope, element, attrs) {
      scope.$on(attrs.focusOn, function(e) {
        $timeout((function() {
          element[0].focus();
        }), 10);
      });
    }
  };
});
HTML:


我真的很喜欢这个解决方案。但是,您能解释一下使用$timeout的原因吗?您使用它的原因是因为“Angular Thing”或“DOM Thing”?它确保它在Angular执行的任何摘要周期之后运行,但这不包括在超时后执行的异步操作之后受影响的摘要周期。谢谢!对于那些想知道这在angular文档中的引用位置的人,这里是(我花了很长时间才找到的)@Ryeball,谢谢!。很好的简单解决方案。只是个问题。我可以使用通过属性创建的工厂,而不是等待某个事件发生吗?在angular中,仅聚焦输入所需的工作量太大了。当
myCondition
$scope变量已设置为true,然后用户选择聚焦到另一个元素时,会发生什么,当
myCondition
已经为真时,您是否仍能重新触发焦点,您的代码会监视属性
focusOnCondition
的更改,但当您尝试更改的值仍然相同时,它不会触发。我将更新示例,在我们的示例中,我们有两个单选按钮,我们根据值将标志切换为true或false,您可以将myCondition标志更改为true或false,这似乎是一个通用的解决方案。比依赖ID要好。我喜欢它。如果其他人尝试了它,但它不起作用,我必须更改元素。focus();到元素[0]。焦点();这个解决方案比上面基于id的黑客更“角度化”,注意:只有在使用完整的jQuery而不是依赖嵌入在angular中的jqLite时,这才有效。请看,这是jQuery的方法,而不是角度的方法。这个问题特别问如何以一种有角度的方式去做。这很好,对我来说一直都很好。但是现在我有了一组使用
ng repeat
的输入,我只想为第一个设置focus函数。你知道我如何根据
$index
等有条件地为
设置聚焦函数吗?很高兴这很有用。我的angular 1有点生疏,但您应该能够向输入中添加另一个属性,如
assign focus function if=“{{{$index==0}}”
,然后作为指令的第一行在assignin之前退出
app.directive('inputFocusFunction', function () {
    'use strict';
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            scope[attr.inputFocusFunction] = function () {
                element[0].focus();
            };
        }
    };
});
<input input-focus-function="focusOnSaveInput" ng-model="saveName">
<button ng-click="focusOnSaveInput()">Focus</button>
$scope.focusOnSaveInput();
angular.element('#<elementId>').focus();
angular.element('#txtUserId').focus();
angular.module("app").directive("focusOn", function($timeout) {
  return {
    restrict: "A",
    link: function(scope, element, attrs) {
      scope.$on(attrs.focusOn, function(e) {
        $timeout((function() {
          element[0].focus();
        }), 10);
      });
    }
  };
});
<input type="text" name="text_input" ng-model="ctrl.model" focus-on="focusTextInput" />
//Assume this is within your controller
//And you've hit the point where you want to focus the input:
$scope.$broadcast("focusTextInput");