2016-11-19 75 views
1

我有一個指令,可以在點擊時打開一個子菜單,但是我想通過僅在點擊目標元素時激活文檔點擊來改進它。所以問題是改進這個指令或者如何動態添加主機監聽器。Angular 2在指令中動態添加主監聽器

import { Directive, HostListener, Input, AfterContentInit, ElementRef, ViewContainerRef, ContentChild } from '@angular/core'; 

@Directive({ 
    selector: '[appSubMenu]' 
}) 

export class SubMenuDirective implements AfterContentInit { 
    private visible: boolean = false; 
    @ContentChild('subMenu') child: ElementRef; 

    constructor(private vcRef: ViewContainerRef) { } 

    ngAfterContentInit() { 
     this.child.nativeElement.style.display = 'none'; 
    } 

    @HostListener('document:click', ['$event', '$event.target']) 
    show(event:MouseEvent, targetElem: HTMLElement): void { 
     if (this.vcRef.element.nativeElement === targetElem && !this.visible) { 
      this.child.nativeElement.style.display = 'block'; 
      this.visible = true; 
     } else { 
      this.child.nativeElement.style.display = 'none'; 
      this.visible = false; 
     } 
    } 
} 

回答

5

您可以使用Renderer類實現動態事件綁定。存在着兩種功能:

  • listen:從一個元素
  • listenGlobal監聽事件:要收聽全球性活動如文檔,身體

所以你的情況看起來會像下面這樣:

import { Directive, HostListener, Input, AfterContentInit, ElementRef, ViewContainerRef, ContentChild } from '@angular/core'; 

@Directive({ 
    selector: '[appSubMenu]' 
}) 

export class SubMenuDirective implements AfterContentInit { 
    private visible: boolean = false; 
    private unregister: Function; 
    @ContentChild('subMenu') child: ElementRef; 

    constructor(private vcRef: ViewContainerRef, private renderer: Renderer) { } 

    ngAfterContentInit() { 
     this.child.nativeElement.style.display = 'none'; 
    } 


    @HostListener('click', ['$event']) 
    elementClicked(event: MouseEvent) { 
     this.visible = !this.visible; 
     if (this.visible) { 
      this.unregister = this.renderer.listenGlobal('document', 'click',() => { 
       this.child.nativeElement.style.display = 'none'; 
       this.unregister(); 
      }); 
     } else { 
      this.child.nativeElement.style.display = 'block'; 
     } 
    } 
}