在AngularJS中,“Angular的方法”是什么?
更具体的要求:
当打开一个模态时,将焦点设置在这个模态内预定义的<input>上。 每次<input>变得可见时(例如,通过单击某个按钮),将焦点设置在它上。
我尝试用自动对焦来实现第一个要求,但这只在Modal第一次打开时有效,并且只在某些浏览器中有效(例如在Firefox中它不起作用)。
在AngularJS中,“Angular的方法”是什么?
更具体的要求:
当打开一个模态时,将焦点设置在这个模态内预定义的<input>上。 每次<input>变得可见时(例如,通过单击某个按钮),将焦点设置在它上。
我尝试用自动对焦来实现第一个要求,但这只在Modal第一次打开时有效,并且只在某些浏览器中有效(例如在Firefox中它不起作用)。
当前回答
我认为这个指令是不必要的。使用HTML id和类属性选择所需的元素,并让服务使用文档。getElementById或document。querySelector来应用焦点(或jQuery等价物)。
标记是标准的HTML/angular指令,添加了id/classes供选择
<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()强制一个摘要循环
其他回答
这也可以使用ngModelController。使用1.6以上版本(不知道是否使用旧版本)。
HTML
<form name="myForm">
<input type="text" name="myText" ng-model="myText">
</form>
JS
$scope.myForm.myText.$$element.focus();
--
注意:根据上下文的不同,您可能需要封装一个超时函数。
注意²:当使用controllerAs时,这几乎是相同的。只需将name="myForm"替换为name="vm "。在JS中,vm.myForm.myText.$$element.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);
});
}
});
如果所需的焦点元素被注入到指令模板中,前面的所有答案都将不起作用。 下面的指令既适用于简单元素,也适用于指令注入的元素(我用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 />
内部元素的使用示例(通常用于动态注入元素,如directive with template):
<my-directive focus-on-load="input" />
你可以使用任何jQuery选择器来代替“input”
这工作得很好,并以一种角度的方式来聚焦输入控件
angular.element('#elementId').focus()
虽然这不是一种纯粹的角方式来完成任务,但语法遵循了角风格。Jquery使用Angular间接和直接访问DOM (jQLite => Jquery Light)。
如果需要,这段代码可以很容易地放在一个简单的角指令中,其中element可以直接访问。
下面的指令对我来说很管用。对输入使用相同的autofocus html属性。
.directive('autofocus', [function () {
return {
require : 'ngModel',
restrict: 'A',
link: function (scope, element, attrs) {
element.focus();
}
};
}])