在AngularJS中,“Angular的方法”是什么?
更具体的要求:
当打开一个模态时,将焦点设置在这个模态内预定义的<input>上。 每次<input>变得可见时(例如,通过单击某个按钮),将焦点设置在它上。
我尝试用自动对焦来实现第一个要求,但这只在Modal第一次打开时有效,并且只在某些浏览器中有效(例如在Firefox中它不起作用)。
在AngularJS中,“Angular的方法”是什么?
更具体的要求:
当打开一个模态时,将焦点设置在这个模态内预定义的<input>上。 每次<input>变得可见时(例如,通过单击某个按钮),将焦点设置在它上。
我尝试用自动对焦来实现第一个要求,但这只在Modal第一次打开时有效,并且只在某些浏览器中有效(例如在Firefox中它不起作用)。
当前回答
如果所需的焦点元素被注入到指令模板中,前面的所有答案都将不起作用。 下面的指令既适用于简单元素,也适用于指令注入的元素(我用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”
其他回答
你可以创建一个指令,将焦点集中在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,因为postlinks只发生在HTML处理中。
HTML有一个属性autofocus。
<input type="text" name="fname" autofocus>
http://www.w3schools.com/tags/att_input_autofocus.asp
Mark和Blesh有很好的答案;然而,Mark的回答有一个Blesh指出的缺陷(除了实现复杂之外),我觉得Blesh的回答在创建一个专门向前端发送焦点请求的服务时存在语义错误,而实际上他所需要的只是一种延迟事件的方法,直到所有指令都在侦听。
这就是我最后做的事情,从Blesh的答案中窃取了很多,但保持了控制器事件和“after load”服务的语义分离。
这允许控制器事件很容易被其他事情所吸引,而不仅仅是聚焦一个特定的元素,还允许只在需要时才引起“after load”功能的开销,在很多情况下可能不是这样。
使用
<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);
}
});
一个简单的情态动词:
.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 />
不确定依赖超时是否是一个好主意,但这适用于ng-repeat,因为这段代码在angularjs更新DOM后运行,所以你要确保所有对象都在那里:
myApp.directive('onLastRepeat', [function () {
return function (scope, element, attrs) {
if (scope.$last) setTimeout(function () {
scope.$emit('onRepeatLast', element, attrs);
}, 1);
};
}]);
//controller for grid
myApp.controller('SimpleController', ['$scope', '$timeout', '$http', function ($scope, $timeout, $http)
{
var newItemRemoved = false;
var requiredAlert = false;
//this event fires up when angular updates the dom for the last item
//it's observed, so here, we stop the progress bar
$scope.$on('onRepeatLast', function (scope, element, attrs) {
//$scope.complete();
console.log('done done!');
$("#txtFirstName").focus();
});
}]);