在AngularJS中将焦点设置在输入字段上的“角度方式”是什么?
更具体的要求:
- 当一个模态被打开,在一组预定义的焦点<input>这里面模态。
- 每次<input>都可见(例如,通过单击某些按钮),将焦点放在其上。
我试图达到第一个要求有autofocus,但只有当模态被打开的第一次,只有在特定的浏览器(如Firefox中这是行不通的)这个作品。
任何帮助将不胜感激。
在AngularJS中将焦点设置在输入字段上的“角度方式”是什么?
更具体的要求:
<input>这里面模态。<input>都可见(例如,通过单击某些按钮),将焦点放在其上。我试图达到第一个要求有autofocus,但只有当模态被打开的第一次,只有在特定的浏览器(如Firefox中这是行不通的)这个作品。
任何帮助将不胜感激。
Answers:
- 打开模态后,将焦点放在此模态内的预定义<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”进行比较,因为@始终会产生字符串。
value != "true",看来可以解决我的问题。
                    马克·拉杰科克(Mark Rajcok)是这个人...他的回答是有效的回答,但是有缺陷(对不起马克)...
...尝试使用布尔将焦点放在输入上,然后使输入模糊,然后尝试使用它再次将输入聚焦。除非将布尔值重置为false,然后将$ digest重置为true,否则它将不起作用。即使在表达式中使用字符串比较,也将不得不将字符串更改为$ digest,然后再将其更改。(这已通过模糊事件处理程序解决。)
因此,我提出了这个替代解决方案:
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在下面发表评论后,我已经稍微更改了执行此操作的方法。现在,我结合使用服务和处理“幕后”事件的指令:
除此之外,它与上面概述的原理相同。
<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);
    });
  }
});$broadcast,$timeout则需要将其包装到。否则不错的解决方案。
                    当您真正需要的是其他一些答案时,我发现这些答案过于复杂
app.directive('autoFocus', function($timeout) {
    return {
        restrict: 'AC',
        link: function(_scope, _element) {
            $timeout(function(){
                _element[0].focus();
            }, 0);
        }
    };
});用法是
<input name="theInput" auto-focus>我们使用超时让dom中的内容呈现,即使它为零,也至少要等待-这样就可以在模式中工作
ng-click:假设单击ng-click="showInput = !showInput输入上的按钮。然后,在您的实际输入上添加ng-if="showInput"。切换按钮将使指令每次重新运行。我在使用时遇到问题,这ng-show是错误的方法。
                    HTML有一个属性autofocus。
<input type="text" name="fname" autofocus>您还可以使用angular内置的jqlite功能。
angular.element('.selector').trigger('focus');
Looking up elements via selectors is not supported by jqLite!
                    这很好用,并且有角度地聚焦输入控制
angular.element('#elementId').focus()尽管这不是完成任务的纯角度方式,但语法遵循角度样式。jQuery间接扮演角色,并使用Angular直接访问DOM(jQLite => JQuery Light)。
如果需要,可以将此代码轻松放入直接访问元素的简单角度指令中。
Looking up elements via selectors is not supported by jqLite!
                    angular.element成为的包装$() / jQuery()。因此,如果没有它,它将无法正常工作,并且您基本上无论如何都只是使用jQuery(但如果我错了,请纠正我)
                    我认为$ 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
这是我的原始解决方案:
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。
我写了一个双向绑定焦点指令,就像最近的模型一样。
您可以像这样使用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>这是小提琴:
对于那些通过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...$timeout用50ms代替0。
                    我发现使用通用表达式很有用。这样,您可以执行诸如在输入文本有效时自动移动焦点之类的操作
<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
                        }
                    }
                });
            }
        }
    };
});不要复活僵尸或插入我自己的指令(好吧,这正是我在做的事情):
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
        };
    }
})();首先,官方的重点关注方法是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/
ngFocus似乎是处理方式focus的事件,而不是一个方法来设置焦点的元素上。
                    除了创建自己的指令之外,还可以简单地使用javascript函数来完成焦点。
这是一个例子。
在html文件中:
<input type="text" id="myInputId" />在文件javascript中,例如在控制器中要激活焦点的位置:
document.getElementById("myInputId").focus();如果您只是想要一个由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();
                });
            });
        }
    }
});您可以只创建一个指令,以强制关注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处理时发生。
马克和布莱什有很好的答案。但是,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);
  }
});这也可以使用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();。
可能是ES6时代最简单的解决方案。
添加以下一个线性指令可使HTML“ autofocus”属性在Angular.js上有效。
.directive('autofocus', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())}))现在,您可以使用HTML5自动对焦语法,例如:
<input type="text" autofocus>.directive('autofocus', ['$timeout', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())})])
                    这里只是一个新手,但是我很想让这个指令在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 />以下指令对我有用。使用相同的autofocus html属性进行输入。
.directive('autofocus', [function () {
    return {
        require : 'ngModel',
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.focus();
        }
    };
}])如果您正在使用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让该方法告诉您何时可以聚焦;)
希望对您有所帮助!:)
如果将所需的焦点元素注入指令模板中,则所有先前的答案均无效。以下指令适合简单元素或指令注入元素(我在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选择器代替“输入”
我编辑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.解决方案应独立于父控制器范围,以增加可重用性。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
<select id="ddl00">  
 <option>"test 01"</option>  
</select>javascript
document.getElementById("ddl00").focus();如果您希望将重点放在特定元素上,则可以使用以下方法。
创建一个名为的服务focus。
angular.module('application')
.factory('focus', function ($timeout, $window) {
    return function (id) {
        $timeout(function () {
            var element = $window.document.getElementById(id);
            if (element)
                element.focus();
        });
    };
});从您要呼叫的地方将其注入控制器。
致电此服务。
我认为该指令是不必要的。使用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()强制进行摘要循环