我是Angular JS的新手,并且新版本的Angular 2已经到位,我在实现指令时遇到了麻烦,该指令可以处理强制关注点击按钮时打开的模态的指令。
过去曾提出过几个类似的问题,答案在Angular 1中如下:
app.directive('focusMe',
['$timeout',
function ($timeout) {
return {
link: {
pre: function preLink(scope, element, attr) {
// ...
},
post: function postLink(scope, element, attr) {
$timeout(function () {
element[0].focus();
}, 0);
}
}
}
}]);
});
我正在尝试在Angular 2中转换同一段代码。但我不确定如何实现它。任何人都可以通过向我提供有关如何实现这一目标的更多信息来指出我正确的方向。
编辑:
我尝试按如下方式实现该指令,当我调试代码时,我甚至看到该指令被调用,但我仍然无法关注模态对话框中的元素:
import { Directive, ElementRef } from "@angular/core";
@Directive({
selector: "[ModFocus]"
})
export class ModalFocus {
constructor(private _el: ElementRef) {
this._el.nativeElement.focus();
}
}
我在这里做错了吗?或者除了在nativeElement上调用focus()之外我还需要做其他事情吗?
HTML模式:
<div class="modal-dialog modal-sm" tabindex="-1">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Are you sure?</h4>
</div>
<div class="modal-body">
Warning
</div>
<div class="modal-footer ok-cancel" ModFocus>
<button type="button" class="btn btn-default" (click)="cancel()">Cancel</button>
<button type="button" class="btn btn-primary" (click)="delete()" data-dismiss="modal">Delete</button>
</div>
</div>
</div>
谢谢。
答案 0 :(得分:5)
使用Angular 2创建组件时,使用与AngularJS相比的不同语法。您的示例代码可能如下所示:
import { Component, ElementRef, ViewChild } from "@angular/core";
@Component({
selector: "whatever",
template: `<input #myControl type='input'/>`
})
export class MyComponent {
@ViewChild("myControl") myCtrl: ElementRef;
constructor () {
// This is wrong. It should be done in ngOnInit not in the
// constructor as the element might not yet be available.
//this.myCtrl.nativeElement.focus();
}
}
我是在没有检查的情况下从头脑中写出来的,但是这应该让你对你应该去的方向有个很好的了解。
当你更新问题时,我认为这是错误的。在新代码中,您将在构造函数中设置焦点。可能是您的视图仍未生成,因此您想要设置焦点的元素仍然不可用(在我之前的示例中,当我在构造函数中实例化时,我误导了您,当我想要OnInit
。我为此道歉。)。我会做以下事情:
import { Directive, ElementRef, OnInit } from "@angular/core";
@Directive({
selector: "[ModFocus]"
})
export class ModalFocus implements OnInit {
constructor(private _el: ElementRef) {
}
ngOnInit(): any {
// At this point, your element should be available.
this._el.nativeElement.focus();
}
}
OnInit
是Angular 2发出的lifecycle hooks之一。我建议你通过它们来获得更好的理解。
问题是Directives
没有模板。对添加它们的元素的行为。创建指令时,其构造函数如下所示:
构造函数(private el:ElementRef,private renderer:Renderer){}
el
应该可以访问this.el.nativeElement.focus()
请看一下有关Attribute Directives
的angular.io上的这篇文章答案 1 :(得分:2)
我在问题中执行指令实际上是正确的。焦点没有进入模态的问题是因为tabindex = -1放置错误。
以下是我创建的指令。我没有直接使用ElementRef。相反,我使用Renderer作为明确提到的Angular文档来避免使用security risk标记的类。
import { Directive, ElementRef, Renderer} from "@angular/core";
@Directive({
selector: "[ModFocus]"
})
export class modalFocus {
constructor(private _el: ElementRef, private renderer: Renderer) {
this.renderer.invokeElementMethod(this._el.nativeElement, 'focus');
}
}
HTML:
<div class="modal fade" tabindex="-1">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Are you sure?</h4>
</div>
<div class="modal-body">
Warning
</div>
<div class="modal-footer ok-cancel">
<button type="button" class="btn btn-default" (click)="cancel()" ModFocus>Cancel</button>
<button type="button" class="btn btn-primary" (click)="delete()" data-dismiss="modal">Delete</button>
</div>
</div>
</div>
</div>
在上面的html中,我实际上错过了使用类模态淡化的主标签上的tabindex。添加tabindex会在打开时将焦点集中在模态上的按钮上。
Husein提供了宝贵的意见,这些意见非常有帮助。因此,我接受他的回答。再次感谢Husein。
答案 2 :(得分:0)
trapFocus(){
// add all the elements inside modal which you want to make focusable
const focusableElements = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
const modal:any = document.querySelector('#deactivate-modal'); // select the modal by it's id
const firstFocusableElement = modal.querySelectorAll(focusableElements)[0]; // get first element to be focused inside modal
const focusableContent = modal.querySelectorAll(focusableElements);
const lastFocusableElement = focusableContent[focusableContent.length - 1]; // get last element to be focused inside modal
document.addEventListener('keydown', function(e) {
let isTabPressed = e.key === 'Tab' || e.keyCode === 9;
if (!isTabPressed) {
return;
}
if (e.shiftKey) { // if shift key pressed for shift + tab combination
if (document.activeElement === firstFocusableElement) {
lastFocusableElement.focus(); // add focus for the last focusable element
e.preventDefault();
}
} else { // if tab key is pressed
if (document.activeElement === lastFocusableElement) { // if focused has reached to last focusable element then focus first focusable element after pressing tab
firstFocusableElement.focus(); // add focus for the first focusable element
e.preventDefault();
}
}
});
firstFocusableElement.focus();
}