2016-11-19 73 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'; 
     } 
    } 
}