如果使用 *ngIf 删除子组件,则会触发 Angular 自定义 clickaway 侦听器 [英] Angular custom clickaway listener is triggered if a child component is removed using *ngIf
问题描述
我有一个 clickaway 监听器作为指令,它使用 @HostListener
放在 App.component.ts
@Component({选择器:应用程序根",templateUrl: "./app.component.html",styleUrls: [./app.component.css"],})导出类 AppComponent {构造函数(私有点击:ClickawayService){}@HostListener("document:click", ["$event"]) documentClick(event: any): void {this.clickaway.target.next(event.target);}}
@Directive({选择器:[clickaway]",})导出类 ClickawayDirective 实现 OnInit、OnDestroy {@Input() clickaway = null;私人订阅:订阅 = 空;构造函数(私人 clickawayService: ClickawayService,私有 eleRef: ElementRef) {}ngOnInit() {this.subscription = this.clickawayService.target.subscribe((target) => {if (!this.eleRef.nativeElement.contains(target)) {this.clickaway();}});}ngOnDestroy() {this.subscription.unsubscribe();}}
ClickAway
服务只是提供了一个主题来监听 AppComponent
上的 document:click
.
我在一个由 *ngIf 控制的 div 上使用这个指令,例如:
<span *ngIf=isVisible"><按钮(点击)=closeSpan()">关闭</button>//closeSpan() 将 isVisible 设置为 false.</span>
问题是每当我点击关闭时,它也会触发 clickaway 的 doSomething 功能.
我知道 *ngIf 从 dom 中删除了跨度,因此当指令运行时 !this.eleRef.nativeElement.contains(target)
评估为 false,因为元素不存在.
到目前为止我尝试过的是:
closeSpan() {setTimeout(() => this.isVisible = false, 100);}
并使用 position: absolute
和非常高的偏移量将跨度移出视图并删除 *ngIf
.
这些解决方案有效,但我正在寻找一种更优雅的方式,最好是指令本身处理这种情况.
谢谢
尝试更改 *ngIf:
<按钮(点击)=closeSpan()">关闭</button>//closeSpan() 将 isVisible 设置为 false.</span>
对于隐藏:
<按钮(点击)=closeSpan()">关闭</button>//closeSpan() 将 isVisible 设置为 false.</span>
I have a clickaway listener as a directive that uses @HostListener
put on App.component.ts
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
constructor(private clickaway: ClickawayService) {}
@HostListener("document:click", ["$event"]) documentClick(event: any): void {
this.clickaway.target.next(event.target);
}
}
@Directive({
selector: "[clickaway]",
})
export class ClickawayDirective implements OnInit, OnDestroy {
@Input() clickaway = null;
private subscription: Subscription = null;
constructor(
private clickawayService: ClickawayService,
private eleRef: ElementRef
) {}
ngOnInit() {
this.subscription = this.clickawayService.target.subscribe((target) => {
if (!this.eleRef.nativeElement.contains(target)) {
this.clickaway();
}
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
The ClickAway
service just provides a subject to listen to document:click
on the AppComponent
.
I am using this directive on a div that has child controlled by *ngIf, something like:
<div [clickaway]="doSomething">
<span *ngIf="isVisible">
<button (click)="closeSpan()">close</button> //closeSpan() sets isVisible to false.
</span>
</div>
The problem is whenever I click on close, it also triggers the clickaway's doSomething function.
I understand that *ngIf removes the span from dom thus when the directive runs !this.eleRef.nativeElement.contains(target)
evaluates to false, since element is not there.
What I have tried so far is:
closeSpan() {
setTimeout(() => this.isVisible = false, 100);
}
and moving the span out of view using position: absolute
and very high offsets and removing *ngIf
.
These solutions work, but I am seeking a more elegant way, preferably the directive itself handling such cases.
Thanks
Try to change the *ngIf:
<span *ngIf="isVisible">
<button (click)="closeSpan()">close</button> //closeSpan() sets isVisible to false.
</span>
For hidden:
<span [hidden]="!isVisible">
<button (click)="closeSpan()">close</button> //closeSpan() sets isVisible to false.
</span>
这篇关于如果使用 *ngIf 删除子组件,则会触发 Angular 自定义 clickaway 侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!