Angular 2 - 关闭组件失败

时间:2017-03-14 16:57:39

标签: angular angular2-template

使用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

1 个答案:

答案 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>