在AngularJS中,“Angular的方法”是什么?

更具体的要求:

当打开一个模态时,将焦点设置在这个模态内预定义的<input>上。 每次<input>变得可见时(例如,通过单击某个按钮),将焦点设置在它上。

我尝试用自动对焦来实现第一个要求,但这只在Modal第一次打开时有效,并且只在某些浏览器中有效(例如在Firefox中它不起作用)。


当前回答

只是顺便送点咖啡。

app.directive 'ngAltFocus', ->
    restrict: 'A'
    scope: ngAltFocus: '='
    link: (scope, el, attrs) ->
        scope.$watch 'ngAltFocus', (nv) -> el[0].focus() if nv

其他回答

HTML有一个属性autofocus。

<input type="text" name="fname" autofocus>

http://www.w3schools.com/tags/att_input_autofocus.asp

我发现使用一般的表达方式很有用。这样你就可以在输入文本有效时自动移动焦点

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

该指令的代码:

.directive('mooFocusExpression', function ($timeout) {
    return {
        restrict: 'A',
        link: {
            post: function postLink(scope, element, attrs) {
                scope.$watch(attrs.mooFocusExpression, function (value) {

                    if (attrs.mooFocusExpression) {
                        if (scope.$eval(attrs.mooFocusExpression)) {
                            $timeout(function () {
                                element[0].focus();
                            }, 100); //need some delay to work with ng-disabled
                        }
                    }
                });
            }
        }
    };
});

##(编辑:我已经在这个解释下面添加了一个更新的解决方案)

马克·拉杰科克是…他的答案是一个有效的答案,但它有一个缺陷(对不起,马克)…

…尝试使用布尔值来聚焦输入,然后模糊输入,然后尝试再次使用它来聚焦输入。它不会工作,除非你重置布尔值为假,然后$digest,然后重置为真。即使在表达式中使用字符串比较,也必须将字符串更改为其他内容$digest,然后再更改回来。(这个问题已经通过模糊事件处理程序解决了。)

所以我提出了这个替代方案:

使用事件,Angular中被遗忘的特性。

JavaScript终究喜欢事件。事件本质上是松散耦合的,更好的是,您可以避免向$摘要中添加另一个$watch。

app.directive('focusOn', function() {
   return function(scope, elem, attr) {
      scope.$on(attr.focusOn, function(e) {
          elem[0].focus();
      });
   };
});

所以现在你可以这样使用它:

<input type="text" focus-on="newItemAdded" />

然后在应用程序的任何地方。

$scope.addNewItem = function () {
    /* stuff here to add a new item... */

    $scope.$broadcast('newItemAdded');
};

这太棒了,因为你可以用它做各种各样的事情。首先,你可以把已经存在的事件联系起来。另一方面,你开始做一些聪明的事情,让应用程序的不同部分发布事件,让应用程序的其他部分可以订阅。

无论如何,这种类型的东西对我来说就是“事件驱动”。我认为作为Angular开发人员,我们真的很努力地把$scope形状的钉子钉进事件形状的洞里。

这是最好的解决方案吗?我不知道。这是一个解决方案。


更新的解决方案

在@ShimonRachlenko下面的评论之后,我稍微改变了我的方法。现在我使用服务和指令的组合来处理“幕后”事件:

除此之外,它与上面概述的原理相同。

下面是一个快速的Plunk演示

# # #使用

<input type="text" focus-on="focusMe"/>
app.controller('MyCtrl', function($scope, focus) {
    focus('focusMe');
});

# # #源

app.directive('focusOn', function() {
   return function(scope, elem, attr) {
      scope.$on('focusOn', function(e, name) {
        if(name === attr.focusOn) {
          elem[0].focus();
        }
      });
   };
});

app.factory('focus', function ($rootScope, $timeout) {
  return function(name) {
    $timeout(function (){
      $rootScope.$broadcast('focusOn', name);
    });
  }
});

我写了一个双向绑定焦点指令,就像最近的model。

你可以像这样使用focus指令:

<input focus="someFocusVariable">

如果你在控制器的任何地方设置someFocusVariable范围变量为真,输入就会被聚焦。如果你想“模糊”你的输入,someFocusVariable可以设置为false。这就像Mark Rajcok的第一个答案,但是有双向绑定。

下面是指令:

function Ctrl($scope) {
  $scope.model = "ahaha"
  $scope.someFocusVariable = true; // If you want to focus initially, set this to true. Else you don't need to define this at all.
}

angular.module('experiement', [])
  .directive('focus', function($timeout, $parse) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
          scope.$watch(attrs.focus, function(newValue, oldValue) {
              if (newValue) { element[0].focus(); }
          });
          element.bind("blur", function(e) {
              $timeout(function() {
                  scope.$apply(attrs.focus + "=false"); 
              }, 0);
          });
          element.bind("focus", function(e) {
              $timeout(function() {
                  scope.$apply(attrs.focus + "=true");
              }, 0);
          })
      }
    }
  });

用法:

<div ng-app="experiement">
  <div ng-controller="Ctrl">
    An Input: <input ng-model="model" focus="someFocusVariable">
    <hr>
        <div ng-click="someFocusVariable=true">Focus!</div>  
        <pre>someFocusVariable: {{ someFocusVariable }}</pre>
        <pre>content: {{ model }}</pre>
  </div>
</div>

这是小提琴:

http://fiddle.jshell.net/ubenzer/9FSL4/8/

我想在寻找一个更好的解决方案,但没有找到它,而是不得不创造它之后,为这个讨论做出贡献。

标准: 1. 解决方案应该独立于父控制器范围,以增加可重用性。 2. 避免使用$watch来监视某些条件,这既缓慢,又增加了摘要循环的大小,并且使测试更加困难。 3.避免$timeout或$scope.$apply()触发摘要循环。 4. input元素出现在使用Directive打开的元素中。

这是我最喜欢的解决方案:

指令:

.directive('focusInput', [ function () {
    return {
        scope: {},
        restrict: 'A',
        compile: function(elem, attr) {
            elem.bind('click', function() {
                elem.find('input').focus();                
            });
        }        
    };
}]);

Html:

 <div focus-input>
     <input/>
 </div>

我希望这篇文章能帮助到一些人!