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

更具体的要求:

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

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


当前回答

不需要创建自己的指令,可以简单地使用javascript函数来完成一个焦点。

这里有一个例子。

在html文件中:

<input type="text" id="myInputId" />

在javascript文件中,例如在控制器中,你想要激活焦点的地方:

document.getElementById("myInputId").focus();

其他回答

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

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

…尝试使用布尔值来聚焦输入,然后模糊输入,然后尝试再次使用它来聚焦输入。它不会工作,除非你重置布尔值为假,然后$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);
    });
  }
});

这是我最初的解决方案:

砰砰作响

var app = angular.module('plunker', []);
app.directive('autoFocus', function($timeout) {
    return {
        link: function (scope, element, attrs) {
            attrs.$observe("autoFocus", function(newValue){
                if (newValue === "true")
                    $timeout(function(){element[0].focus()});
            });
        }
    };
});

而HTML:

<button ng-click="isVisible = !isVisible">Toggle input</button>
<input ng-show="isVisible" auto-focus="{{ isVisible }}" value="auto-focus on" />

它的作用:

使用ng-show,当输入变得可见时,它会聚焦输入。没用$watch和$on。

首先,关注1.1的路线图是一种正式的方式。同时,您可以编写一个指令来实现设置焦点。

其次,在一个项目变得可见之后设置焦点,目前需要一个变通方法。只是用$timeout延迟对元素focus()的调用。

因为同样的控制器-修改- dom问题存在于焦点,模糊和选择,我建议有一个ng-target指令:

<input type="text" x-ng-model="form.color" x-ng-target="form.colorTarget">
<button class="btn" x-ng-click="form.colorTarget.focus()">do focus</button>

Angular线程在这里:http://goo.gl/ipsx4,更多细节在这里:http://goo.gl/4rdZa

下面的指令将在你的控制器中创建一个由ng-target属性指定的.focus()函数。(它也创建了.blur()和.select()。)演示:http://jsfiddle.net/bseib/WUcQX/

以编程方式调用元素上的任何操作:click(), focus(), select()…

用法:

<a href="google.com" auto-action="{'click': $scope.autoclick, 'focus': $scope.autofocus}">Link</a>

指令:

/**
 * Programatically Triggers given function on the element
 * Syntax: the same as for ng-class="object"
 * Example: <a href="google.com" auto-action="{'click': autoclick_boolean, 'focus': autofocus_boolean}">Link</a>
 */
app.directive('focusMe', function ($timeout) {
    return {
        restrict: 'A',
        scope: {
            autoAction: '<',
        },
        link: function (scope, element, attr) {
            const _el = element[0];
            for (const func in scope.autoAction) {
                if (!scope.autoAction.hasOwnProperty(func)) {
                    continue;
                }
                scope.$watch(`autoAction['${func}']`, (newVal, oldVal) => {
                    if (newVal !== oldVal) {
                        $timeout(() => {
                            _el[func]();
                        });
                    }
                });
            }

        }
    }
});

要解决这个问题,最好在controller或ng-init中设置初始化变量:

 <input ng-init="autofocus=true" auto-action="{'focus': autofocus}">

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

标准: 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>

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