AngularでclickイベントとstopPropagationを使ってドロップダウンメニューを外部クリックで閉じる

2024-04-11

Angular でドロップダウンメニューを外部クリックで閉じる方法

click イベントと stopPropagation メソッド

HTML

<div class="dropdown">
  <button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
    メニュー
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
    <li><a class="dropdown-item" href="#">アイテム1</a></li>
    <li><a class="dropdown-item" href="#">アイテム2</a></li>
  </ul>
</div>

JavaScript

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor() {}

  closeDropdown(event: any) {
    if (!event.target.classList.contains('dropdown-toggle')) {
      event.stopPropagation();
      const dropdown = document.querySelector('.dropdown');
      dropdown.classList.remove('show');
    }
  }
}

この方法では、click イベントリスナーを document 要素に追加し、クリックされた要素がドロップダウンメニューのボタン以外だった場合、stopPropagation メソッドを使ってイベント伝播を阻止し、ドロップダウンメニューを閉じるようにしています。

Overlay サービス

Angular Material の Overlay サービスを使うと、より簡単にドロップダウンメニューを外部クリックで閉じることができます。

<div class="dropdown">
  <button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" (click)="openDropdown()">
    メニュー
  </button>
  <div class="dropdown-menu" [cdkConnectedOverlay]="overlay" (click)="closeDropdown()">
    <a class="dropdown-item" href="#">アイテム1</a>
    <a class="dropdown-item" href="#">アイテム2</a>
  </div>
</div>
import { Component, OnInit } from '@angular/core';
import { Overlay, OverlayConfig } from '@angular/cdk/overlay';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  private overlay: Overlay;

  constructor(private overlayService: Overlay) {}

  ngOnInit() {
    this.overlay = this.overlayService.create(new OverlayConfig());
  }

  openDropdown() {
    this.overlay.attach(new TemplatePortal(this.dropdownMenuTemplateRef));
  }

  closeDropdown() {
    this.overlay.detach();
  }
}

この方法では、Overlay サービスを使ってドロップダウンメニューをオーバーレイとして表示し、click イベントリスナーを使って外部クリック時に Overlay をデタッチすることで、ドロップダウンメニューを閉じることができます。

ngx-bootstrap ライブラリを使うと、さらに簡単にドロップダウンメニューを作成・管理できます。

<div class="dropdown">
  <button type="button" class="btn btn-primary dropdown-toggle" bsDropdown>
    メニュー
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#">アイテム1</a></li>
    <li><a class="dropdown-item" href="#">アイテム2</a></li>
  </ul>
</div>
import { Component } from '@angular/core';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  imports: [BsDropdownModule]
})
export class AppComponent {

  constructor() {}
}

ngx-bootstrap ライブラリを使うと、bsDropdown ディレクティブを追加するだけでドロップダウンメニューを作成できます。また、outsideClick オプションを `true




click イベントと stopPropagation メソッド

<div class="dropdown">
  <button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
    メニュー
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
    <li><a class="dropdown-item" href="#">アイテム1</a></li>
    <li><a class="dropdown-item" href="#">アイテム2</a></li>
  </ul>
</div>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor() {}

  closeDropdown(event: any) {
    if (!event.target.classList.contains('dropdown-toggle')) {
      event.stopPropagation();
      const dropdown = document.querySelector('.dropdown');
      dropdown.classList.remove('show');
    }
  }
}

Overlay サービス

<div class="dropdown">
  <button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" (click)="openDropdown()">
    メニュー
  </button>
  <div class="dropdown-menu" [cdkConnectedOverlay]="overlay" (click)="closeDropdown()">
    <a class="dropdown-item" href="#">アイテム1</a>
    <a class="dropdown-item" href="#">アイテム2</a>
  </div>
</div>
import { Component, OnInit } from '@angular/core';
import { Overlay, OverlayConfig } from '@angular/cdk/overlay';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  private overlay: Overlay;

  constructor(private overlayService: Overlay) {}

  ngOnInit() {
    this.overlay = this.overlayService.create(new OverlayConfig());
  }

  openDropdown() {
    this.overlay.attach(new TemplatePortal(this.dropdownMenuTemplateRef));
  }

  closeDropdown() {
    this.overlay.detach();
  }
}

ngx-bootstrap ライブラリ

<div class="dropdown">
  <button type="button" class="btn btn-primary dropdown-toggle" bsDropdown>
    メニュー
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#">アイテム1</a></li>
    <li><a class="dropdown-item" href="#">アイテム2</a></li>
  </ul>
</div>
import { Component } from '@angular/core';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';

@Component({
  selector: 'my-component',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  imports: [BsDropdownModule]
})
export class AppComponent {

  constructor() {}
}



HostListener デコレータを使って、ドロップダウンメニューの要素に click イベントリスナーを追加することができます。

import { Component, HostListener } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor() {}

  @HostListener('document:click', ['$event'])
  closeDropdown(event: any) {
    if (!event.target.classList.contains('dropdown-toggle')) {
      const dropdown = document.querySelector('.dropdown');
      dropdown.classList.remove('show');
    }
  }
}

EventEmitterOutput デコレータを使って、ドロップダウンメニューが閉じられたことを親コンポーネントに通知することができます。

子コンポーネント

<div class="dropdown">
  <button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
    メニュー
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
    <li><a class="dropdown-item" href="#">アイテム1</a></li>
    <li><a class="dropdown-item" href="#">アイテム2</a></li>
  </ul>
</div>
import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'my-dropdown',
  templateUrl: './dropdown.component.html',
  styleUrls: ['./dropdown.component.css']
})
export class DropdownComponent {

  @Output() closed = new EventEmitter();

  constructor() {}

  closeDropdown() {
    this.closed.emit();
  }
}
<my-dropdown (closed)="onDropdownClosed()"></my-dropdown>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor() {}

  onDropdownClosed() {
    // ドロップダウンメニューが閉じられた時の処理
  }
}
<div class="dropdown">
  <button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
    メニュー
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton" (ng-click)="closeDropdown()">
    <li><a class="dropdown-item" href="#">アイテム1</a></li>
    <li><a class="dropdown-item" href="#">アイテム2</a></li>
  </ul>
</div>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor() {}

  closeDropdown() {
    const dropdown = document.querySelector('.dropdown');
    dropdown.classList.remove('show');
  }
}

これらの方法の中から、ご自身のプロジェクトに合った方法を選択してください。


javascript drop-down-menu angular


ReactJSコンポーネントの名前を分かりやすく付けるための4つのポイント

ReactJSは、コンポーネントとHTML要素を区別するために、JSXと呼ばれる構文を使用します。JSXでは、HTML要素と同じようにコンポーネントを記述することができます。上記のコードは、div要素とh1要素を含むHTMLコードです。JSXでは、コンポーネントを以下の2つの方法で記述することができます。...


JavaScriptでasync/awaitを使って複数の非同期処理を実行する

解説:Promise. allは、複数の非同期処理をまとめて実行し、すべての処理が完了した時に結果を返すPromiseオブジェクトを生成します。Node. jsのイベントループは、非同期処理を効率的に処理するために設計されています。イベントループは、処理待ちのキューと、実行中の処理のスタックを持ちます。...


NgxScriptLoader モジュールを使った外部スクリプトの動的ロード

@dynamic 属性を使うこの方法は、Angular 12 以降で推奨されています。この方法では、@dynamic 属性を使用して、script 要素を動的に作成できます。Renderer2 を使うDomSanitizer を使うこの方法は、セキュリティ上のリスクを回避するために使用できます。...


ngClass ディレクティブでホスト要素に動的にクラスを追加/削除する

ngClass ディレクティブは、コンポーネントのホスト要素に動的にクラスを追加または削除するために使用できます。この例では、isActive プロパティが true の場合、active クラスがホスト要素に追加されます。@HostBinding デコレータは、コンポーネントクラスのメンバー変数をホスト要素のプロパティにバインドするために使用できます。...


AngularとFirebaseでシングルページアプリケーションを開発しよう!

Angularのルーティングは、主に以下の要素で構成されています。Router: ルーティングを管理するクラスです。URLの変化を監視し、対応するコンポーネントを表示します。Route: どのURLがどのコンポーネントに対応するかを定義する情報です。パス、コンポーネントクラス、データなどを含みます。...


SQL SQL SQL SQL Amazon で見る



参考資料:RFC 5322、email-validator、js-email-validation

JavaScriptでメールアドレスを検証するには、いくつかの方法があります。正規表現:最も一般的な方法です。メールアドレスの形式に合致するかどうかをチェックします。HTML5のinput type="email"属性: HTML5で導入された属性です。ブラウザが自動的に検証を行います。


JavaScript クロージャーの仕組みを徹底解説! 3つのスコープとメモリリークへの対策

JavaScriptでは、関数内にある変数は、その関数内でしかアクセスできません。しかし、クロージャーを使用すると、関数内にある変数を、関数外からでもアクセスすることができます。これは、関数内にある変数が、関数オブジェクトの一部として保持されるためです。つまり、関数が実行された後も、その変数はメモリに残っているのです。


JavaScriptとjQueryで要素外のクリックを検出する方法

JavaScript と jQuery を使用して、特定の要素外のクリックを検出する方法はいくつかあります。 以下では、最も一般的な 3 つの方法を紹介します。方法 1: $(document).click() イベントを使用するこの方法は、ドキュメント全体で発生するすべてのクリックイベントを処理し、クリックされた要素が特定の要素内かどうかをチェックします。


スッキリ理解!jQueryで要素の表示・非表示を判定する5つのテクニック

jQueryには、要素の状態を判別するための様々なメソッドが用意されています。その中でも、要素が隠れているかどうかを確認するには、以下の3つの方法が主に使用されます。:visible 擬似クラスセレクタis(':hidden') メソッドoffset().top プロパティ


Object.defineProperty() メソッドを使って JavaScript オブジェクトからプロパティを削除する方法

delete 演算子を使用する最も簡単な方法は、delete 演算子を使用することです。 構文は以下の通りです。例えば、以下のオブジェクトから name プロパティを削除するには、次のように記述します。Object. defineProperty() メソッドを使用して、プロパティの configurable 属性を false に設定することで、プロパティを削除不可にすることができます。


ページ遷移をスムーズに!JavaScript と jQuery によるリダイレクトテクニック

JavaScript でリダイレクトするには、以下のコードを使用します。上記のコードはすべて、https://www. example. com/ という URL にリダイレクトします。location. href と window. location


JavaScriptファイルに別のJavaScriptファイルを含める方法

<script>タグを使うこれは最も簡単な方法です。HTMLファイルに以下のコードを追加します。このコードは、ブラウザに別ファイル名. jsを読み込むように指示します。importステートメントを使うこれはES6で導入された新しい方法です。以下のコードのように、importステートメントを使ってファイルをインポートできます。


【徹底比較】JavaScriptで部分文字列の存在を確認する3つの方法のメリットとデメリット

String. prototype. includes() メソッド概要includes() メソッドは、指定された部分文字列が文字列内に含まれているかどうかを調べ、真偽値を返します。最もシンプルで分かりやすい方法です。例メリットシンプルで分かりやすい


パフォーマンスアップ!JavaScript 配列から要素を効率的に削除する方法

splice() メソッドを使うこれは最も一般的で、柔軟な方法です。splice() メソッドは、配列の要素を追加、削除、置き換えることができます。引数 start: 削除を開始するインデックス deleteCount: 削除する要素の数


XMLHttpRequestとFetch APIを使いこなす

そこで登場したのが非同期通信です。非同期通信は、ユーザーがアクションを起こしてもページ全体を再読み込みすることなく、必要なデータのみをサーバーと通信で取得・更新する技術です。これにより、ユーザー操作のレスポンス向上やページ読み込み時間の短縮を実現できます。