2017-04-27 10 views
0

私のヘッダにドロップダウンメニューが働くように指示を出しました。今のところ@DirectiveデコレータのhostListenersプロパティを使用する代わりに、バニラのJavaScriptメソッドを使用しています。コードは、私が関数を匿名関数の代わりに独自の関数としてリファクタリングするまで動作していました。関数のリファクタリング時にaddEventListenerを使用すると、角ディレクティブでエラーが発生する

import { Directive, OnInit, ElementRef, OnDestroy } from '@angular/core'; 

@Directive({ 
    selector: '[headerDropdown]' 
}) 
export class HeaderDropdownDirective implements OnInit, OnDestroy { 

    private isActive: boolean; 
    private isAbove: boolean; 

    private dropDownElement: Element; 
    private downArrowElement: Element; 

    constructor(private elementRef: ElementRef) { } 

    ngOnInit() { 
     this.dropDownElement = document.querySelector('.header__dropdown'); 
     this.downArrowElement = this.elementRef.nativeElement; 

     this.downArrowElement.addEventListener('mouseenter', this.downArrowOnMouseEnter); 
     this.downArrowElement.addEventListener('mouseleave', this.downArrowOnMouseLeave); 
     this.downArrowElement.addEventListener('click', this.downArrowOnClick); 
     document.addEventListener('click', this.documentOnClick); 
    } 

    ngOnDestroy() { 
     // TODO: removeEventListener 
    } 

    private activate() { 
     this.isActive = true; 
     this.downArrowElement.classList.add('header__item--active'); 
     this.dropDownElement.classList.add('header__dropdown--active'); 
    } 

    private deActivate() { 
     this.isActive = false; 
     this.downArrowElement.classList.remove('header__item--active'); 
     this.dropDownElement.classList.remove('header__dropdown--active'); 
    } 

    private downArrowOnMouseEnter() { 
     this.isAbove = true; 
    } 

    private downArrowOnMouseLeave() { 
     this.isAbove = false; 
    } 

    private downArrowOnClick() { 
     if (!this.isActive) { 
      this.activate(); 
     } else { 
      this.deActivate(); 
     } 
    } 

    private documentOnClick() { 
     if (!this.isAbove) { 
      this.deActivate(); 
     } 
    } 

} 

私はクリックするか、単にDOWNARROWボタンと対話するときに私が取得エラー:

EXCEPTION: this.activate is not a function 
ErrorHandler.handleError @ VM12616:55 
next @ VM12615:374 
schedulerFn @ VM12630:100 
SafeSubscriber.__tryOrUnsub @ VM12634:236 
SafeSubscriber.next @ VM12634:185 
Subscriber._next @ VM12634:125 
Subscriber.next @ VM12634:89 
Subject.next @ VM12631:55 
EventEmitter.emit @ VM12630:86 
NgZone.triggerError @ VM12629:335 
onHandleError @ VM12629:296 
ZoneDelegate.handleError @ zone.js?fad3:246 
Zone.runTask @ zone.js?fad3:154 
ZoneTask.invoke @ zone.js?fad3:345 
VM12616:60 ORIGINAL STACKTRACE: 
ErrorHandler.handleError @ VM12616:60 
next @ VM12615:374 
schedulerFn @ VM12630:100 
SafeSubscriber.__tryOrUnsub @ VM12634:236 
SafeSubscriber.next @ VM12634:185 
Subscriber._next @ VM12634:125 
Subscriber.next @ VM12634:89 
Subject.next @ VM12631:55 
EventEmitter.emit @ VM12630:86 
NgZone.triggerError @ VM12629:335 
onHandleError @ VM12629:296 
ZoneDelegate.handleError @ zone.js?fad3:246 
Zone.runTask @ zone.js?fad3:154 
ZoneTask.invoke @ zone.js?fad3:345 
VM12616:61 TypeError: this.activate is not a function 
    at HTMLDivElement.HeaderDropdownDirective.downArrowOnClick (eval at <anonymous> (main.js:3477), <anonymous>:49:18) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (main.js:5060), <anonymous>:275:35) 
    at Object.onInvokeTask (eval at <anonymous> (main.js:1076), <anonymous>:266:37) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (main.js:5060), <anonymous>:274:40) 
    at Zone.runTask (eval at <anonymous> (main.js:5060), <anonymous>:151:47) 
    at HTMLDivElement.ZoneTask.invoke (eval at <anonymous> (main.js:5060), <anonymous>:345:33) 
ErrorHandler.handleError @ VM12616:61 
next @ VM12615:374 
schedulerFn @ VM12630:100 
SafeSubscriber.__tryOrUnsub @ VM12634:236 
SafeSubscriber.next @ VM12634:185 
Subscriber._next @ VM12634:125 
Subscriber.next @ VM12634:89 
Subject.next @ VM12631:55 
EventEmitter.emit @ VM12630:86 
NgZone.triggerError @ VM12629:335 
onHandleError @ VM12629:296 
ZoneDelegate.handleError @ zone.js?fad3:246 
Zone.runTask @ zone.js?fad3:154 
ZoneTask.invoke @ zone.js?fad3:345 
VM12634:240 Uncaught TypeError: this.activate is not a function 
    at HTMLDivElement.HeaderDropdownDirective.downArrowOnClick (eval at <anonymous> (main.js:3477), <anonymous>:49:18) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (main.js:5060), <anonymous>:275:35) 
    at Object.onInvokeTask (eval at <anonymous> (main.js:1076), <anonymous>:266:37) 
    at ZoneDelegate.invokeTask (eval at <anonymous> (main.js:5060), <anonymous>:274:40) 
    at Zone.runTask (eval at <anonymous> (main.js:5060), <anonymous>:151:47) 
    at HTMLDivElement.ZoneTask.invoke (eval at <anonymous> (main.js:5060), <anonymous>:345:33) 

しかし、私はこれにコードを変更した場合、それは動作します:

import { Directive, OnInit, ElementRef, OnDestroy } from '@angular/core'; 

@Directive({ 
    selector: '[headerDropdown]' 
}) 
export class HeaderDropdownDirective implements OnInit, OnDestroy { 

    private isActive: boolean; 
    private isAbove: boolean; 

    private dropDownElement: Element; 
    private downArrowElement: Element; 

    constructor(private elementRef: ElementRef) { } 

    ngOnInit() { 
     this.dropDownElement = document.querySelector('.header__dropdown'); 
     this.downArrowElement = this.elementRef.nativeElement; 

     this.downArrowElement.addEventListener('mouseenter',() => { this.isAbove = true; }); 
     this.downArrowElement.addEventListener('mouseleave',() => { this.isAbove = false; }); 

     this.downArrowElement.addEventListener('click',() => { 
      if (!this.isActive) { 
       this.activate(); 
      } else { 
       this.deActivate(); 
      }    
     }); 

     document.addEventListener('click',() => { 
      if (!this.isAbove) { 
       this.deActivate(); 
      }    
     }); 
    } 

    ngOnDestroy() { 
     // TODO: removeEventListener 
    } 

    private activate() { 
     this.isActive = true; 
     this.downArrowElement.classList.add('header__item--active'); 
     this.dropDownElement.classList.add('header__dropdown--active'); 
    } 

    private deActivate() { 
     this.isActive = false; 
     this.downArrowElement.classList.remove('header__item--active'); 
     this.dropDownElement.classList.remove('header__dropdown--active'); 
    } 

} 

I問題を理解していない。私はまた、プライベートではない機能を作ろうとしましたが、それでもうまくいかず、同じエラーが発生します。

答えて

2

変更

this.downArrowElement.addEventListener('mouseenter', this.downArrowOnMouseEnter); 
this.downArrowElement.addEventListener('mouseleave', this.downArrowOnMouseLeave); 
this.downArrowElement.addEventListener('click', this.downArrowOnClick); 
document.addEventListener('click', this.documentOnClick); 

this.downArrowElement.addEventListener('mouseenter', this.downArrowOnMouseEnter.bind(this)); 
this.downArrowElement.addEventListener('mouseleave', this.downArrowOnMouseLeave).bind(this); 
this.downArrowElement.addEventListener('click', this.downArrowOnClick.bind(this)); 
document.addEventListener('click', this.documentOnClick.bind(this)); 

へのご thisは、これらの機能の下でディレクティブに参照のうえされていません。

+1

ありがとうございます!今私は理由を理解する。それはクラスではなく関数のthisを使います。 – Alex

関連する問題