簡體   English   中英

指令在角度 6 外單擊

[英]directive click outside angular 6

我將我的 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>

看法:

<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');
    }
  }
}

您在模板中引用了“this” ,這是不必要的。 我做了一個該指令的工作示例:

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>

這是對上面@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!');
  }
}

在這里,我們在銷毀時刪除事件偵聽器。 另外,通常 addEventListener 添加的方法是在全局上下文(而不是this上下文)中執行的; 所以我們應該照顧它並將onDocumentClick方法綁定到this (我們在ngOnInit )。 現在我們可以在onDocumentClick使用this

運行內部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 (在“突出顯示我!”之外點擊)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM