指令点击外角6

时间:2018-05-25 14:15:09

标签: angular angular2-directives angular6

我将Angular从4升级到6,因此我的点击政策出现问题,它停止了对所有组件的处理。

我的指示:

import { Directive, Output, EventEmitter, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[clickOutside]'
})
export class ClickOutsideDirective {

  constructor(private _elementRef : ElementRef) { }

  @Output()
  public clickOutside = new EventEmitter();

  @HostListener('document:click', ['$event.target'])
  public onClick(targetElement) {
      const clickedInside = this._elementRef.nativeElement.contains(targetElement);
      if (!clickedInside) {
          this.clickOutside.emit(null);
      }
  }
}

我使用此指令的component.html:

<div id="sidenav" *ngIf="this.opened" class="sidenav" [ngClass]="getClasses()" [ngStyle]="getStyles()" clickOutside (clickOutside)="closeOutsideSidenav()">
  <header> {{ navTitle }} </header>
  <i *ngIf="this.showCloseButton" class="iconic iconic-x-thin close-icon" (click)="closeSidenav()"></i>
  <ng-content></ng-content>
</div>
<div *ngIf="this.backdrop && this.opened" class="sidenav-backdrop"></div>

4 个答案:

答案 0 :(得分:6)

这是@YoungHyeong Ryu上面答案的一种修改,但是已取消订阅,因此,在卸载组件时处理程序将停止工作。

演示 https://stackblitz.com/edit/angular-1q4pga

import { Component, Input, OnInit, OnDestroy, ViewChild } from '@angular/core';

@Component({
  selector: 'app-click-outside',
  template: `<div #insideElement>Click outside me.</div>`
})
export class ClickOutsideComponent implements OnInit, OnDestroy  {
  @ViewChild('insideElement', { static: false }) insideElement;

  public ngOnInit() {
    this.onDocumentClick = this.onDocumentClick.bind(this);
    document.addEventListener('click', this.onDocumentClick);
  }

  public ngOnDestroy() {
    document.removeEventListener('click', this.onDocumentClick);
  }

  protected onDocumentClick(event: MouseEvent) {
    if (this.insideElement.nativeElement.contains(event.target)) {
      return;
    }
    console.log('Clicked outside!');
  }
}

在这里,我们在destroy上删除事件监听器。 同样,通常由addEventListener添加的方法是在全局上下文(而不是this上下文)中执行的;因此我们应该照顾好它,并将onDocumentClick方法绑定到this(我们在ngOnInit中进行)。现在我们可以在this内使用onDocumentClick

答案 1 :(得分:5)

您在模板中引用&#34;此&#34; ,这是不必要的。我做了一个关于该指令的工作示例:

https://stackblitz.com/edit/angular-piqewb

并且没有理由两次对div进行指令。

<div id="sidenav" *ngIf="opened" class="sidenav" [ngClass]="getClasses()" [ngStyle]="getStyles()" (clickOutside)="closeOutsideSidenav()">
    <header> {{ navTitle }} </header>
    <i *ngIf="showCloseButton" class="iconic iconic-x-thin close-icon" (click)="closeSidenav()"></i>
    <ng-content></ng-content>
</div>

<div *ngIf="backdrop && opened" class="sidenav-backdrop"></div>

答案 2 :(得分:3)

视图:

<div #insideElement></div>

组件:

export class SomeClass {
  @ViewChild("insideElement") insideElement;
  @HostListener('document:click', ['$event.target'])

  public onClick(targetElement) {
    const clickedInside = this.insideElement.nativeElement.contains(targetElement);
    if (!clickedInside) {
      console.log('outside clicked');
    }
  }
}

答案 3 :(得分:-1)

运行内部NgZone

示例:

export class AppComponent {
  opened: boolean = false;

  constructor(private ngZone: NgZone) {
  }

  closeOutsideSidenav(e) {
    this.ngZone.run(() => {
      this.opened = !this.opened;
    })
  }
}

我将我的代码添加到stackblitz。 https://stackblitz.com/edit/angular-gyhtym(点击“#34;突出显示我!&#34;”外面的