AngularでclickイベントとstopPropagationを使ってドロップダウンメニューを外部クリックで閉じる
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');
}
}
}
EventEmitter
と Output
デコレータを使って、ドロップダウンメニューが閉じられたことを親コンポーネントに通知することができます。
子コンポーネント
<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