Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Angularで範囲外をクリックしたイベントを取得する

More than 3 years have passed since last update.

やりたいこと

「開いているウィンドウの範囲外をクリックしたら、ウィンドウを閉じる」といった動きを実現する際に、範囲外をクリックしたイベントを取得したい。

jQueryで言うところの、
範囲外クリックでポップアップを閉じる正しい JQuery

自分で実装

Output、EventEmitterの仕組みを使えば、簡単に実装できました。
イメージ的には、「子コンポーネントでグローバルなクリックイベントを拾って、そのイベントが自分に対するものではなかったら、親コンポーネントにイベントを投げる」と言った感じです。

子コンポーネント

Output, EventEmitter, HostListener, ElementRefをインポートし、ElementRefをconstructorでDIします。

child.component.ts
import { Output, EventEmitter, HostListener, ElementRef } from '@angular/core';

constructor(
    private elementRef: ElementRef
) {}

コンポーネントの範囲外がクリックされたことを親コンポーネントに通知するためのイベントのバインディングを定義します。

child.component.ts
@Output() clickOutside = new EventEmitter<MouseEvent>();

HostListenerデコレータを宣言した後に、範囲外がクリックされたことを検知するメソッドをバインドします。

child.component.ts
  onClickOutsidefDetailSearch(event: MouseEvent, targetElement: HTMLElement) {
    const clickedInside = this.elementRef.nativeElement.contains(targetElement);
    if (!clickedInside) {
      this.clickOutside.emit(event);
    }
  }

親コンポーネント

clickOutsideイベントを受けるメソッドを定義します。

parent.component.ts
  onClickOutside(event: MouseEvent) {
        console.log(event);
        // 何かする
  }
parent.component.html
<app-child (clickOutside)="onClickOutside($event)"> My element </app-child>

ライブラリを使う

ng-click-outside というライブラリがあるようです。

先に紹介した自分で実装する方法では、個々のコンポーネントに一連の実装を行う必要がありましたが、こちらのライブラリでは、ディレクティブとして機能が使えるため、めちゃ楽です。

使ってみる

インストール

$ npm install --save ng-click-outside

インポート

app.module.ts
import { ClickOutsideModule } from 'ng-click-outside';

@NgModule({
  ...
  imports: [
    ...
    ClickOutsideModule
    ],
    ...
})
class AppModule {}

clickOutsideイベントを受けるメソッドを定義します。

parent.component.ts
  onClickOutside(event: MouseEvent) {
        console.log(event);
        // 何かする
  }

好きなエレメント、コンポーネントにディレクティブを追加します。

parent.component.html
<div (clickOutside)="onClickOutside($event)">My element</div>

参考

https://qiita.com/mabots/items/74c21ebcedf0004f7fb5
https://github.com/valor-software/ngx-bootstrap/issues/1823

終わりに

今回紹介した内容を実装するにあたって、参考に記載したgithubのissueを参考に自分で実装した後に、便利なライブラリがあることに気づきました...
HostListenerをの使い方を再確認するいい機会になったかと思います。
とりあえずng-click-outsideを使いましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away