web-dev-qa-db-ja.com

ディレクティブを使用して、angular 4の要素の外側のクリックを検出

カスタムディレクティブを使用してangular 2の要素の外側のクリックを検出しましたが、angular 4では同じことはできません。

[plunkr]https://plnkr.co/edit/aKcZVQ?p=info

Angle-4で同じコードを使用しようとすると、次のエラーが発生します:

1. Argument of type '{ template: string; directives: typeof ClickOutside[]; }' is not assignable to parameter of type 'Component'. ==> 

    @Component({
    templateUrl: "",
    directives: [ClickOutside]
    })


2. Type 'Subscription' is not assignable to type 'Observable<MouseEvent>'. in the directive inside ngOnInit() and ngOnDestroy() 

ngOnInit() {
    this.globalClick = Observable
        .fromEvent(document, 'click')
        .delay(1)
        .do(() => {
            this.listening = true;
         }).subscribe((event:MouseEvent) => {
            this.onGlobalClick(event);
         });
}

ngOnDestroy() {
    this.globalClick.unsubscribe();
}

angular 4のディレクティブ宣言に変更があった場合、私に知らせてください。公式文書はこの問題の助けにはなりません。

20
Ronit Oommen

Plnkrに関連する変更はほとんどありません。

  1. NgModules 、またはフレームワークの Archietcture をご覧ください。モジュールは、コンポーネント、サービス、および指示を登録する場所です
  2. モジュール内にディレクティブを登録したら、コンポーネント内にインポートする必要はありません

ディレクティブ自体は私には問題ありません。 Angular 4.3.5で正常に動作する私のディレクティブとあなたのディレクティブを比較しました。

実際、繰り返し使用されない限り、その場合はディレクティブは必要ありません。そのclickOutsideをメニューにのみ適用する必要がある場合は、次のように実行することをお勧めします。

そのような「内部」セレクターにクリックイベントをバインドします。あなたのメニューだとしましょう:

  <ul id="menu" (click)="clickedInside($event)"> <li> .. </li> </ul>

次に、コンポーネント内に次のようなclickedInside()関数を追加します。

  clickedInside($event: Event){
    $event.preventDefault();
    $event.stopPropagation();  // <- that will stop propagation on lower layers
    console.log("CLICKED INSIDE, MENU WON'T HIDE");
  }

最後に、コンポーネントで Host Listener を使用して、ドキュメントの残りの部分にもクリックをバインドできます。

  @HostListener('document:click', ['$event']) clickedOutside($event){
    // here you can hide your menu
    console.log("CLICKED OUTSIDE");
  }
50
Kuba