如果使用 *ngIf 删除子组件,则会触发 Angular 自定义 clickaway 侦听器 [英] Angular custom clickaway listener is triggered if a child component is removed using *ngIf

查看:32
本文介绍了如果使用 *ngIf 删除子组件,则会触发 Angular 自定义 clickaway 侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆