以angular度方式设置元素焦点
在查找如何设置angular度的焦点元素的例子之后,我看到他们中的大多数使用一些variables来观察然后设置焦点,并且他们中的大多数对于每个他们想要设置焦点的场使用一个不同的variables。 在一个forms上,有很多领域,这意味着在很多不同的variables。
以jQuery的方式,但想要以angular度的方式做到这一点,我做了一个解决scheme,我们使用元素的id在任何函数中设置焦点,所以,因为我是非常新的angular度,我想获得一些意见,如果这种方式是正确的,有问题,无论如何,任何事情都可以帮助我以更好的方式做到这一点。
基本上,我创build了一个指令,通过指令来监视由用户定义的范围值,或者默认的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将会这样做
<input my-focus id="input1" type="text" />
这里有任何设置焦点的元素:
<a href="" ng-click="clickButton()" >Set focus</a>
而关注的例子function:
$scope.clickButton = function() { $scope.focusElement = "input1"; }
这是angular度的一个很好的解决scheme吗? 有没有问题,我的经验不足,我还没有看到?
解决scheme的问题在于,当绑定到创build新范围的其他指令(如ng-repeat
时,该方法效果不佳。 一个更好的解决scheme是简单地创build一个服务函数,使您可以在控制器中强制性地关注元素,或者在html中声明性地关注元素。
DEMO
JAVASCRIPT
服务
.factory('focus', function($timeout, $window) { return function(id) { // timeout makes sure that it is invoked after any other event has been triggered. // eg click events that need to run before the focus or // inputs elements that are in a disabled state but are enabled when those events // are triggered. $timeout(function() { var element = $window.document.getElementById(id); if(element) element.focus(); }); }; });
指示
.directive('eventFocus', function(focus) { return function(scope, elem, attr) { elem.on(attr.eventFocus, function() { focus(attr.eventFocusId); }); // Removes bound events in the element itself // when the scope is destroyed scope.$on('$destroy', function() { elem.off(attr.eventFocus); }); }; });
调节器
.controller('Ctrl', function($scope, focus) { $scope.doSomething = function() { // do something awesome focus('email'); }; });
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>
关于这个解决scheme,我们可以创build一个指令,并将其附加到满足给定条件时必须获得焦点的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
<input focus-on-condition="myCondition">
我希望尽可能避免DOM查找,监视和全局排放,所以我使用更直接的方法。 使用指令来分配一个简单的函数,该函数专注于指令元素。 然后在控制器范围内的任何地方调用该函数。
这是将其附加到范围的简化方法。 查看处理controller-as语法的完整代码片段。
指示:
app.directive('inputFocusFunction', function () { 'use strict'; return { restrict: 'A', link: function (scope, element, attr) { scope[attr.inputFocusFunction] = function () { element[0].focus(); }; } }; });
和在HTML中:
<input input-focus-function="focusOnSaveInput" ng-model="saveName"> <button ng-click="focusOnSaveInput()">Focus</button>
或在控制器中:
$scope.focusOnSaveInput();
angular.module('app', []) .directive('inputFocusFunction', function() { 'use strict'; return { restrict: 'A', link: function(scope, element, attr) { // Parse the attribute to accomodate assignment to an object var parseObj = attr.inputFocusFunction.split('.'); var attachTo = scope; for (var i = 0; i < parseObj.length - 1; i++) { attachTo = attachTo[parseObj[i]]; } // assign it to a function that focuses on the decorated element attachTo[parseObj[parseObj.length - 1]] = function() { element[0].focus(); }; } }; }) .controller('main', function() {});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script> <body ng-app="app" ng-controller="main as vm"> <input input-focus-function="vm.focusOnSaveInput" ng-model="saveName"> <button ng-click="vm.focusOnSaveInput()">Focus</button> </body>
你可以试试
angular.element('#<elementId>').focus();
例如。
angular.element('#txtUserId').focus();
它为我工作。
另一个select是使用Angular的内置pub-sub体系结构来通知你的指令来关注。 与其他方法类似,但它不直接绑定到某个属性,而是倾听特定密钥的范围。
指示:
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 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");
我最喜欢用一个expression。 这可以让我做一些事情,如当一个字段有效,达到一定的长度,当然在加载之后,重点放在一个button上。
<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">
在复杂的forms上,这也减less了为了聚焦而创build额外的范围variables的需要。