如何设置对输入字段的关注?


759

在AngularJS中将焦点设置在输入字段上的“角度方式”是什么?

更具体的要求:

  1. 当一个模态被打开,在一组预定义的焦点<input>这里面模态。
  2. 每次<input>都可见(例如,通过单击某些按钮),将焦点放在其上。

我试图达到第一个要求autofocus,但只有当模态被打开的第一次,只有在特定的浏览器(如Firefox中这是行不通的)这个作品。

任何帮助将不胜感激。

Answers:


579
  1. 打开模态后,将焦点放在此模态内的预定义<input>上。

定义一个指令,并使其$ watch一个属性/触发器,以便它知道何时集中该元素:

Name: <input type="text" focus-me="shouldBeOpen">

app.directive('focusMe', ['$timeout', '$parse', function ($timeout, $parse) {
    return {
        //scope: true,   // optionally create a child scope
        link: function (scope, element, attrs) {
            var model = $parse(attrs.focusMe);
            scope.$watch(model, function (value) {
                console.log('value=', value);
                if (value === true) {
                    $timeout(function () {
                        element[0].focus();
                    });
                }
            });
            // to address @blesh's comment, set attribute value to 'false'
            // on blur event:
            element.bind('blur', function () {
                console.log('blur');
                scope.$apply(model.assign(scope, false));
            });
        }
    };
}]);

柱塞

$ timeout似乎需要给定模态时间来渲染。

'2。每当<input>变为可见时(例如,通过单击某些按钮),请将焦点设置在它上面。

创建一个基本上与上述指令相似的指令。观察一些scope属性,当它变为true(在ng-click处理程序中设置)时,执行execute element[0].focus()。根据您的用例,您可能需要也可能不需要$ timeout:

<button class="btn" ng-click="showForm=true; focusInput=true">show form and
 focus input</button>
<div ng-show="showForm">
  <input type="text" ng-model="myInput" focus-me="focusInput"> {{ myInput }}
  <button class="btn" ng-click="showForm=false">hide form</button>
</div>

app.directive('focusMe', function($timeout) {
  return {
    link: function(scope, element, attrs) {
      scope.$watch(attrs.focusMe, function(value) {
        if(value === true) { 
          console.log('value=',value);
          //$timeout(function() {
            element[0].focus();
            scope[attrs.focusMe] = false;
          //});
        }
      });
    }
  };
});

柱塞


更新7/2013:我已经看到一些人使用我原来的隔离范围指令,然后在嵌入的输入字段(即模态中的输入字段)方面遇到问题。没有新作用域(或可能新的子作用域)的指令应减轻某些痛苦。因此,以上我更新了不使用隔离范围的答案。以下是原始答案:

1.使用隔离范围的原始答案:

Name: <input type="text" focus-me="{{shouldBeOpen}}">

app.directive('focusMe', function($timeout) {
  return {
    scope: { trigger: '@focusMe' },
    link: function(scope, element) {
      scope.$watch('trigger', function(value) {
        if(value === "true") { 
          $timeout(function() {
            element[0].focus(); 
          });
        }
      });
    }
  };
});

柱塞

2.使用隔离范围的原始答案:

<button class="btn" ng-click="showForm=true; focusInput=true">show form and
 focus input</button>
<div ng-show="showForm">
  <input type="text" focus-me="focusInput">
  <button class="btn" ng-click="showForm=false">hide form</button>
</div>

app.directive('focusMe', function($timeout) {
  return {
    scope: { trigger: '=focusMe' },
    link: function(scope, element) {
      scope.$watch('trigger', function(value) {
        if(value === true) { 
          //console.log('trigger',value);
          //$timeout(function() {
            element[0].focus();
            scope.trigger = false;
          //});
        }
      });
    }
  };
});

柱塞

由于我们需要在指令中重置trigger / focusInput属性,因此“ =”用于双向数据绑定。在第一个指令中,“ @”就足够了。还要注意,当使用“ @”时,我们将触发值与“ true”进行比较,因为@始终会产生字符串。


1
另请参见@Josh的“ focus”指令:stackoverflow.com/a/14859639/215945 他没有在实现中使用隔离范围。
Mark Rajcok

2
@MarkRajcok对此感到好奇:此版本有效,但是如果我ng-model在输入字段上设置了一个,当我使用带有隔离范围的指令时,模型值会丢失。如果我尝试带隔离范围的Josh版本,则不会发生此问题。仍然是新手,我想了解两者之间的区别。这是一个显示它的柱塞
Sunil D.

1
我发现#1与AngularJS 1.0.6搭配得很好。但是,在调试器下运行时,我注意到每次解雇并重新打开模态时,都会看到对设置焦点的函数的调用比以前多了一次。我稍微修改了该功能,以在解除绑定手表的功能value != "true",看来可以解决我的问题。
安德鲁·布朗

1
所以...在有状态页面上,我也有同样的事情,因为$ watch是$ watch,而角度开发人员也喜欢$ watch ...好吧,我遇到了一个问题,@ MarkRajcok先生,这个问题我已经用(基本)解决方案解决了建议如下。
Ben Lesh

3
对我来说,代码有效,如我所见,它可以正确执行,element [0]是正确的控件。但是.focus()不会触发焦点。可能是自举或其他干扰?
Sonic Soul

264

(编辑:我在此说明下方添加了更新的解决方案)

马克·拉杰科克(Mark Rajcok)是这个人...他的回答是有效的回答,但是缺陷(对不起马克)...

...尝试使用布尔将焦点放在输入上,然后使输入模糊,然后尝试使用它再次将输入聚焦。除非将布尔值重置为false,然后将$ digest重置为true,否则它将不起作用。即使在表达式中使用字符串比较,也将不得不将字符串更改为$ digest,然后再将其更改。(这已通过模糊事件处理程序解决。)

因此,我提出了这个替代解决方案:

使用一个事件,Angular的被遗忘的功能。

JavaScript毕竟热爱事件。事件本质上是松散耦合的,甚至更好的是,您避免在$ digest中添加另一个$ 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);
    });
  }
});

3
如果要使此操作在进入控制器时起作用$broadcast$timeout则需要将其包装到。否则不错的解决方案。
Shimon Rachlenko 2013年

@ShimonRachlenko-谢谢。但是我不确定$ timeout是什么意思。如果我想在处理控制器构造函数时广播,那么我就在那时广播。超时不会做任何事情,只是将广播推迟到事件循环中的以后执行。
Ben Lesh 2013年

1
是的,这足以初始化指令。过量地,该事件在指令开始侦听之前广播。.同样,仅当您想在进入页面时触发指令时才需要此事件。
Shimon Rachlenko 2013年

2
没错 我想我没有用它来关注负载。我将使用更强大的功能更新答案。
Ben Lesh 2013年

1
到目前为止,这是最优雅的“角度方式”解决方案。即使我初次遇到此问题时大多只是复制代码,但我很高兴您为此创建了一个模块!老实说,我认为尝试将其纳入核心角度可能是值得的。
Randolpho

241

当您真正需要的是其他一些答案时,我发现这些答案过于复杂

app.directive('autoFocus', function($timeout) {
    return {
        restrict: 'AC',
        link: function(_scope, _element) {
            $timeout(function(){
                _element[0].focus();
            }, 0);
        }
    };
});

用法是

<input name="theInput" auto-focus>

我们使用超时让dom中的内容呈现,即使它为零,也至少要等待-这样就可以在模式中工作


1
有几种方法可以做到这一点,一种非常简单易行的可能方法是在示波器上(此处为控制器)设置单击按钮时要关注的项目的ID,然后在指令只是听这个。在这种情况下,您不必将指令放置在页面中的任何地方(过去我已经成功使用了这种watcher指令,尤其是在集中注意力和滚动内容方面)-那么,如果重新使用jquery(会使这个过程变得更简单),只需找到该元素的id并将其聚焦
ecancil 2014年

14
如果输入位于弹出模式中,则超时为零的解决方案对我不起作用。但是,即使是10毫秒也能解决问题
Eugene Fidelin

@ecancil:我喜欢您的方法,因为它是最简单的方法,但是您需要在IE中将超时设置为〜500ms,因为模态外观的动画会导致输入之外的光标闪烁。我不知道在动画结束时发生这种情况的好方法,因此我用500ms对其进行了强行处理。
Dev93

将无法正常工作,如果您必须从数据库中提取更多数据,则需要等待控制器完成提取数据,因此添加足够的时间代替0
Ali Adravi 2014年

1
对于像@Ade这样的人,想通过简单的方法使用它ng-click:假设单击ng-click="showInput = !showInput输入上的按钮。然后,在您的实际输入上添加ng-if="showInput"。切换按钮将使指令每次重新运行。我在使用时遇到问题,这ng-show是错误的方法。
JVG

90

HTML有一个属性autofocus

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

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


29
不幸的是,这仅工作一次。我在进行Angular 编辑的情况下使用了此功能,并且第一次在Chrome浏览器中效果很好,而在Firefox中则完全没有。在Chrome浏览器中,当我单击其他项目进行就地编辑时,甚至再次在同一项目上进行编辑时,它不再获得焦点。文档指出它在页面加载时有效,在Angular应用中仅发生一次。如果就这么简单,我们所有人都会坐在海滩上赚取20%的收入!
Nocturno

62

您还可以使用angular内置的jqlite功能。

angular.element('.selector').trigger('focus');


2
没有加载jQuery:angular.forEach(document.querySelectorAll('。selector'),function(elem){elem.focus();});
Dan Benamy 2014年

29
将其放入控制器中不是不好的做法吗?
VitalyB 2014年

2
如果将jqlite行放在控制器中是不好的做法,那么将此jqlite行放在指令中会更好吗?
体育

3
我得到了:Looking up elements via selectors is not supported by jqLite!
Maria Ines Parnisari '16

1
@VitalyB我遇到一种情况,在ajax调用后我需要模糊一个元素。我可以在控制器内部的回调中仅添加一行纯JS,或者专门为模糊输入内容构建整个指令。我只是觉得这太麻烦了,所以我选择了第一选择。
塞巴斯蒂安

55

这很好用,并且有角度地聚焦输入控制

angular.element('#elementId').focus()

尽管这不是完成任务的纯角度方式,但语法遵循角度样式。jQuery间接扮演角色,并使用Angular直接访问DOM(jQLite => JQuery Light)。

如果需要,可以将此代码轻松放入直接访问元素的简单角度指令中。


我不确定这对ViewModel-apps是否适用。在Angular中,必须通过指令来完成。
阿加特2014年

例如,如果有人更改了texbox A,则您需要显示弹出窗口并将焦点放在其他文本框B上。–
Sanjeev Singh

1
使用此工具时出现此错误:Looking up elements via selectors is not supported by jqLite!
JVG 2015年

6
据我所知,您需要首先加载jQuery作为依赖项,在这种情况下,它angular.element成为的包装$() / jQuery()。因此,如果没有它,它将无法正常工作,并且您基本上无论如何都只是使用jQuery(但如果我错了,请纠正我)
JVG 2015年

@Jascination:开发了jqLit​​e来删除jQuery依赖项。您不需要整个jQuery即可访问DOM中的元素。但是,如果您安装了jQuery,则Angular将引用jQuery。检查以下内容:docs.angularjs.org/api/angular.element
Sanjeev Singh

31

我认为$ timeout不是将元素聚焦于创建的好方法。这是一种使用内置角度功能的方法,可从角度文档的模糊深度中挖掘出来。请注意,对于链接前和链接后功能,如何将“链接”属性拆分为“前置”和“后置”。

工作示例:http://plnkr.co/edit/Fj59GB

// this is the directive you add to any element you want to highlight after creation
Guest.directive('autoFocus', function() {
    return {
        link: {
            pre: function preLink(scope, element, attr) {
                console.debug('prelink called');
                // this fails since the element hasn't rendered
                //element[0].focus();
            },
            post: function postLink(scope, element, attr) {
                console.debug('postlink called');
                // this succeeds since the element has been rendered
                element[0].focus();
            }
        }
    }
});
<input value="hello" />
<!-- this input automatically gets focus on creation -->
<input value="world" auto-focus />

完整的AngularJS指令文档:https://docs.angularjs.org/api/ng/service/$compile


2
必须将element [0] .focus()包装在$ timeout中,以使其对我有用。
codin 2015年

@bbodenmiller我的模态应用了淡入淡出的东西,当构造元素时,它是不可见的(100%透明),因此浏览器以静默方式阻止焦点调用。显然,经过了几毫秒的时间,您就可以专注于几乎透明但可见的输入/按钮。
snowindy 2015年

1
根据文档,默认情况下,“链接”功能为“ postLink”。另请参见:bennadel.com/blog/…–
乔迪·泰特

17

这是我的原始解决方案:

塞子

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。


实际上,我相信{{isVisible}}仍在创建手表,因此“不使用$ watch”语句是不正确的。
masimplo 2014年

是的,我认为您是对的。但这仍然是实现此目的的简便方法。
Edhowler

17

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

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

<input focus="someFocusVariable">

如果您使someFocusVariable作用域变量 true在控制器的任何位置都设置了,则输入将变得集中。如果要“模糊”输入,可以将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/


这应该是正确的答案。它涵盖了所有用例。
库纳尔

11

对于那些通过Bootstrap插件使用Angular的用户:

http://angular-ui.github.io/bootstrap/#/modal

您可以opened了解模式实例的承诺:

modalInstance.opened.then(function() {
        $timeout(function() {
            angular.element('#title_input').trigger('focus');
        });
    });

modalInstance.result.then(function ( etc...

好!但是在我的情况下,$timeout50ms代替0
lk_vc 2015年

8

我发现使用通用表达式很有用。这样,您可以执行诸如在输入文本有效时自动移动焦点之类的操作

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

7

不要复活僵尸或插入我自己的指令(好吧,这正是我在做的事情):

https://github.com/hiebj/ng-focus-if

http://plnkr.co/edit/MJS3zRk079Mu72o5A9l6?p=preview

<input focus-if />

(function() {
    'use strict';
    angular
        .module('focus-if', [])
        .directive('focusIf', focusIf);

    function focusIf($timeout) {
        function link($scope, $element, $attrs) {
            var dom = $element[0];
            if ($attrs.focusIf) {
                $scope.$watch($attrs.focusIf, focus);
            } else {
                focus(true);
            }
            function focus(condition) {
                if (condition) {
                    $timeout(function() {
                        dom.focus();
                    }, $scope.$eval($attrs.focusDelay) || 0);
                }
            }
        }
        return {
            restrict: 'A',
            link: link
        };
    }
})();

我现在正在使用此指令,它可以很好地解决一般问题,并且不会过于复杂。放弃寻找无超时的解决方案。不断发现评论指出Angular 1.1和1.2的重点是“在路线图上”,但我使用的是2.x,仍然没有焦点管理。h
tekHedd '16

6

首先,官方的重点关注方法是1.1路线图。同时,您可以编写指令以实现设置焦点。

其次,要在当前可见的项目上设置焦点,需要一种解决方法。只需使用延迟对元素focus()的调用即可$timeout

因为在聚焦,模糊和选择方面存在相同的controller-modified-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>

此处的角度线程:http : //goo.gl/ipsx4,更多详细信息在此处发布:http : //goo.gl/4rdZa

以下指令将.focus()根据ng-target属性指定在控制器内部创建一个函数。(它创建.blur().select()也。)演示:http://jsfiddle.net/bseib/WUcQX/


+1作为路线图参考。其实我刚看到它的文档中的1.2仍然被认为是不稳定(docs.angularjs.org/api/ng.directive:ngFocus
埃德温Dalorzo

27
@EdwinDalorzo ngFocus似乎是处理方式focus的事件,而不是一个方法来设置焦点的元素上。
teleclimber

6

除了创建自己的指令之外,还可以简单地使用javascript函数来完成焦点。

这是一个例子。

在html文件中:

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

在文件javascript中,例如在控制器中要激活焦点的位置:

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

9
这不是“折角方式”,也不建议人们在控制器中接触DOM。
smajl 2014年

最好不要在Angular中使用香草,因为Angular无法跟踪它,也无法使其与其他所有元素保持同步。
Edgar Quintero

4

如果您只是想要一个由ng-click控制的简单焦点。

HTML:

<input ut-focus="focusTigger">

<button ng-click="focusTrigger=!focusTrigger" ng-init="focusTrigger=false"></button>

指示:

'use strict'

angular.module('focus',['ng'])
.directive('utFocus',function($timeout){
    return {
        link:function(scope,elem,attr){
            var focusTarget = attr['utFocus'];
            scope.$watch(focusTarget,function(value){
                $timeout(function(){
                    elem[0].focus();
                });
            });
        }
    }
});

4

一个简单的可以很好地使用模式的方法:

.directive('focusMeNow', ['$timeout', function ($timeout)
{
    return {
        restrict: 'A',

        link: function (scope, element, attrs)
        {


            $timeout(function ()
            {
                element[0].focus();
            });



        }
    };
}])

<input ng-model="your.value" focus-me-now />

适合我。谢谢您
亚历山大

3

您可以只创建一个指令,以强制关注postLinking上的装饰元素:

angular.module('directives')
.directive('autoFocus', function() {
    return {
        restrict: 'AC',
        link: function(_scope, _element) {
            _element[0].focus();
        }
    };
});

然后在您的html中:

<input type="text" name="first" auto-focus/> <!-- this will get the focus -->
<input type="text" name="second"/>

这适用于模式和ng-if切换元素,不适用于ng-show,因为postLinking仅在HTML处理时发生。


3

马克和布莱什有很好的答案。但是,Mark的缺点是Blesh指出了(实施起来很复杂),而且我觉得Blesh的答案在创建服务时存在语义错误,该服务专门用于将焦点请求发送到前端,而实际上他需要的只是一种方法。将事件延迟到所有指令都在侦听为止。

因此,这就是我最终要做的事情,它从Blesh的答案中窃取了很多东西,但是将控制器事件和“加载后”服务的语义分开了。

这使控制器事件可以轻松地挂接到除仅关注特定元素之外的事情上,并且还允许仅在需要时才承担“加载后”功能的开销,而在许多情况下可能不需要。

用法

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

  afterLoad(notifyControllerEvent);
});

资源

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

app.factory('afterLoad', function ($rootScope, $timeout) {
  return function(func) {
    $timeout(func);
  }
});

我(一个完整的初学者)可以理解的唯一答案。我以前不是“ afterLoad(notifyControllerEvent);”,而是“ notifyControllerEvent()”。否则,它以一些错误结束。
Vel Murugan S 2015年

3

这也可以使用ngModelController。使用1.6及更高版本(旧版本不知道)。

的HTML

<form name="myForm">
    <input type="text" name="myText" ng-model="myText">
</form>

JS

$scope.myForm.myText.$$element.focus();

-

注意:根据上下文,您可能需要包装超时功能。

注意:使用时controllerAs,这几乎是相同的。只需在JS name="myForm"中用name="vm.myForm"和替换即可vm.myForm.myText.$$element.focus();


3

可能是ES6时代最简单的解决方案。

添加以下一个线性指令可使HTML“ autofocus”属性在Angular.js上有效。

.directive('autofocus', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())}))

现在,您可以使用HTML5自动对焦语法,例如:

<input type="text" autofocus>

@Stephane是的,所以就变成了.directive('autofocus', ['$timeout', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())})])
Michael Plautz 18-4-25

2

这里只是一个新手,但是我很想让这个指令在ui.bootstrap.modal中工作:

directives.directive('focus', function($timeout) {
    return {
        link : function(scope, element) {
            scope.$watch('idToFocus', function(value) {
                if (value === element[0].id) {
                    $timeout(function() {
                        element[0].focus();
                    });
                }
            });
        }
    };
});

在$ modal.open方法中,我使用以下方法指示应将焦点放在何处的元素:

var d = $modal.open({
        controller : function($scope, $modalInstance) {
            ...
            $scope.idToFocus = "cancelaAteste";
    }
        ...
    });

在模板上我有这个:

<input id="myInputId" focus />

2

以下指令对我有用。使用相同的autofocus html属性进行输入。

.directive('autofocus', [function () {
    return {
        require : 'ngModel',
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.focus();
        }
    };
}])

1
您将运行此错误,除非包括jQuery,否则应为element [0] .focus()
Ryan M

2

如果您正在使用modalInstance并拥有对象,则可以在打开模式后使用“ then”进行操作。如果您不使用modalInstance,并且使用硬编码打开模式,则可以使用该事件。$ timeout不是一个好的解决方案。

您可以执行(Bootstrap3):

$("#" + modalId).on("shown.bs.modal", function() {
    angular.element("[name='name']").focus();
});

在modalInstance上,您可以查看库以了解打开模式后如何执行代码。

不要这样使用$ timeout,$ timeout可以是0、1、10、30、50、200或更大,这取决于客户端计算机以及打开模式的过程。

不要使用$ timeout让该方法告诉您何时可以聚焦;)

希望对您有所帮助!:)


2

如果将所需的焦点元素注入指令模板中,则所有先前的答案均无效。以下指令适合简单元素或指令注入元素(我在typescript中写了它)。它接受内部可聚焦元素的选择器。如果您只需要关注self元素-请勿将任何选择器参数发送到指令:

module APP.Directives {

export class FocusOnLoadDirective implements ng.IDirective {
    priority = 0;
    restrict = 'A';

    constructor(private $interval:any, private $timeout:any) {

    }

    link = (scope:ng.IScope, element:JQuery, attrs:any) => {
        var _self = this;
        var intervalId:number = 0;


        var clearInterval = function () {
            if (intervalId != 0) {
                _self.$interval.cancel(intervalId);
                intervalId = 0;
            }
        };

        _self.$timeout(function(){

                intervalId = _self.$interval(function () {
                    let focusableElement = null;
                    if (attrs.focusOnLoad != '') {
                        focusableElement = element.find(attrs.focusOnLoad);
                    }
                    else {
                        focusableElement = element;
                    }
                    console.debug('focusOnLoad directive: trying to focus');
                    focusableElement.focus();
                    if (document.activeElement === focusableElement[0]) {
                        clearInterval();
                    }
                }, 100);

                scope.$on('$destroy', function () {
                    // Make sure that the interval is destroyed too
                    clearInterval();
                });

        });
    };

    public static factory = ():ng.IDirectiveFactory => {
        let directive = ($interval:any, $timeout:any) => new FocusOnLoadDirective($interval, $timeout);
        directive.$inject = ['$interval', '$timeout'];
        return directive;
    };
}

angular.module('common').directive('focusOnLoad', FocusOnLoadDirective.factory());

}

简单元素的用法示例:

<button tabindex="0" focus-on-load />

内部元素的用法示例(通常用于带有模板指令的动态注入元素):

<my-directive focus-on-load="input" />

您可以使用任何jQuery选择器代替“输入”


2

我编辑Mark Rajcok的focusMe指令,以在一个元素中实现多个焦点。

HTML:

<input  focus-me="myInputFocus"  type="text">

在AngularJs控制器中:

$scope.myInputFocus= true;

AngulaJS指令:

app.directive('focusMe', function ($timeout, $parse) {
    return {
        link: function (scope, element, attrs) {
            var model = $parse(attrs.focusMe);
            scope.$watch(model, function (value) {
                if (value === true) {
                    $timeout(function () {
                        scope.$apply(model.assign(scope, false));
                        element[0].focus();
                    }, 30);
                }
            });
        }
    };
});

1

在寻找更好的解决方案而不是找到它之后,我不得不为它做贡献,而不得不创建它。

准则:1.解决方案应独立于父控制器范围,以增加可重用性。2.避免使用$ watch监视某些情况,因为这既慢,又会增加摘要循环的大小,并使测试更加困难。3.避免$ timeout或$ scope。$ apply()触发摘要循环。4.在使用该指令的元素中存在一个输入元素。

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

指示:

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

我希望这会对外面的人有所帮助!


您只需重新创建html“ label”的功能,就可以将“ div focus-input”替换为“ label”并摆脱指令。
2015年


1

如果您希望将重点放在特定元素上,则可以使用以下方法。

  1. 创建一个名为的服务focus

    angular.module('application')
    .factory('focus', function ($timeout, $window) {
        return function (id) {
            $timeout(function () {
                var element = $window.document.getElementById(id);
                if (element)
                    element.focus();
            });
        };
    });
  2. 从您要呼叫的地方将其注入控制器。

  3. 致电此服务。


0

我认为该指令是不必要的。使用HTML id和class属性选择所需的元素,并使服务使用document.getElementById或document.querySelector来应用焦点(或jQuery等效项)。

标记是标准的HTML / angular指令,带有添加的ID /类供选择

<input id="myInput" type="text" ng-model="myInputModel" />

控制器广播事件

$scope.$emit('ui:focus', '#myInput');

在UI服务中使用querySelector-如果存在多个匹配项(例如由于类),它将仅返回第一个

$rootScope.$on('ui:focus', function($event, selector){
  var elem = document.querySelector(selector);
  if (elem) {
    elem.focus();
  }
});

您可能要使用$ timeout()强制进行摘要循环


0

只是喝点咖啡。

app.directive 'ngAltFocus', ->
    restrict: 'A'
    scope: ngAltFocus: '='
    link: (scope, el, attrs) ->
        scope.$watch 'ngAltFocus', (nv) -> el[0].focus() if nv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.