使用Angular 2,我有一个具有小弹出窗口<div>
的组件。关闭点击将关闭弹出窗口(即,单击文档中的任何位置,弹出窗口将忽略它)。我使用HostListener
来达到效果。
当没有内部元素时,这可以正常工作。但是,如果弹出窗口有内部元素(例如<div class="popup"><p>Inside</p></div>
),则单击弹出窗口将忽略它。这不是理想的行为。
此代码按预期工作:
@Component({
selector: 'my-app',
template: `
<h4 class="example" (click)="showPopup = true">
Click to show popup that works as expected
</h4>
<div *ngIf="showPopup" class="example popup">
Click anywhere besides here to dismiss me
</div>
`,
})
export class App {
public showPopup = false;
@HostListener('document:click', ['$event']) showThePopup(e: Event) {
if (!e.target.classList.contains('example')) {
this.showPopup = false;
}
}
}
但是,以这种方式更改模板将失败:
@Component({
selector: 'my-app',
template: `
<h4 class="example" (click)="showPopup = true">
Click to show popup that work incorrectly
</h4>
<div *ngIf="showPopup" class="example popup">
<p>Clicking here will dismiss me, which should not happen</p>
</div>
`,
})
什么编码方法可以使代码正常工作?
Working Plunker:http://plnkr.co/edit/7viqp6bR8LesM7lCsNQW?p=preview
答案 0 :(得分:2)
我建议你将弹出窗口分成不同的组件,不要试图弄清楚点击元素的任何父元素是否有弹出类,这会为你节省很多麻烦。
这是一个显示概念
的工作Plunker<强>解释强>
当弹出窗口位于其他组件中时,您可以使用ElementRef
访问整个组件的本机元素,然后检查它是否包含click事件的目标。
我们使用mousedown
,以便在(click)
事件被触发之前运行。
@HostListener('document:mousedown', ['$event']) showThePopup(e: Event) {
if(!this._eref.nativeElement.contains(e.target)){
this.showPopup = false;
}
}
通过将定义添加到构造函数中来公开变量_eref
:
constructor(private _eref: ElementRef) { }
在您的父组件中,您可以利用local variables和<ng-content>
来显示弹出窗口:
app.html
<h4 class="example" (click)="mypopup.show()">
Click to show popup that works as expected
</h4>
<popup #mypopup>
<div class="inside"><p>This is a Popup</p></div>
</popup>
popup html
<div *ngIf="showPopup" class="example popup">
<ng-content></ng-content>
</div>