一个明显的正确答案是使用服务并让您的弹出窗口注入该服务并在它们打开和关闭时注册它,以了解当前是否打开了弹出窗口。
但是让我们看看另一个不太明显的解决方案.. 这可能会令人不悦,但对于像这样的小事情,似乎真的是最简单易读的方法。要在 Popover 类上使用静态属性:
@Directive({ selector: '[popover]'})
class Popover {
private static currentPopover: Popover;
private get active() {
return this === Popover.currentPopover;
}
private component: ComponentRef<any>;
constructor(
private vcRef: ViewContainerRef,
private cfResolver: ComponentFactoryResolver,
private elementRef: ElementRef
) {}
@HostListener('document:click')
onDocClick() {
if (this.active) {
this.close();
}
}
@HostListener('click', ['$event'])
toggle(event: MouseEvent) {
if (Popover.currentPopover && !this.active) {
Popover.currentPopover.close();
}
if (!this.active) {
this.open();
event.stopImmediatePropagation();
}
}
open() {
const componentFactory = this.cfResolver.resolveComponentFactory(PopoverWindow);
this.component = this.vcRef.createComponent(componentFactory);
Popover.currentPopover = this;
}
close() {
this.vcRef.clear()
this.component.destroy();
this.component = null;
Popover.currentPopover = undefined;
}
}
我还添加了一个文档点击监听器,所以当你点击其他任何地方时,它会关闭当前的弹出窗口。
plunkr
但如果你愿意使用服务(未经测试的代码):
export class PopoverService {
private activePopover: Popover;
public setActive(popover: Popover): void {
if (this.activePopover) {
this.activePopover.close();
}
this.activePopover = popover;
}
public isActive(popover: Popover): boolean {
return popover === this.activePopover;
}
}
您的指令将如下所示:
@Directive({ selector: '[popover]'})
class Popover {
private get active() {
return this.popoverService.isActive(this);
}
private component: ComponentRef<any>;
constructor(
private vcRef: ViewContainerRef,
private cfResolver: ComponentFactoryResolver,
private elementRef: ElementRef,
private popoverService: PopoverService
) {}
@HostListener('document:click')
onDocClick() {
if (this.active) {
this.close();
}
}
@HostListener('click', ['$event'])
toggle(event: MouseEvent) {
if (!this.active) {
this.open();
event.stopImmediatePropagation();
}
}
open() {
const componentFactory = this.cfResolver.resolveComponentFactory(PopoverWindow);
this.component = this.vcRef.createComponent(componentFactory);
this.popoverService.setActive(this);
}
close() {
this.vcRef.clear()
this.component.destroy();
this.component = null;
}
}