はじめに
Angularに標準で入っているrxjsライブラリを使用してモーダルを共通化することができます!
一つだけモーダルを作っておき、あとはメソッドを呼び出して表示したいタイトル、内容を引数に渡すだけです!
最終的な成果物は動画↓のようになります
1. モーダルの状態を司るサービスの作成
src/app/services/modal.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class ModalService {
private _subject: Subject<{ title: string; body: string } | null> =
new Subject();
constructor() {}
get subject() {
return this._subject;
}
openModal(title: string, body: string) {
this._subject.next({ title, body });
}
closeModal() {
this._subject.next(null);
}
}
2. モーダルコンポーネントの作成
src/app/components/modal.component.html
<div *ngIf="active" class="grayout">
<main>
<header>{{ title }}</header>
<section>{{ body }}</section>
<footer>
<button (click)="closeModal()">OK</button>
</footer>
</main>
</div>
components/modal.component.scss
.grayout {
position: fixed;
top: 0;
left: 0;
background-color: #00000050;
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
main {
width: 500px;
height: 500px;
background-color: #ffffff;
border-radius: 4px;
display: flex;
flex-direction: column;
header {
text-align: center;
margin: 0;
border-radius: 4px 4px 0 0;
color: #ffffff;
background-color: #1976d2;
height: 40px;
line-height: 40px;
}
section {
flex: 1;
padding: 15px;
}
footer {
height: 40px;
display: flex;
padding: 15px;
button {
margin-left: auto;
}
}
}
}
src/app/components/modal.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ModalService } from 'src/app/services/modal.service';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.scss'],
})
export class ModalComponent implements OnInit, OnDestroy {
active = false; // モーダルの表示、非表示を切り替える変数
title = '';
body = '';
subscription: Subscription;
constructor(private modalService: ModalService) {
// subscribeで購読し、タイトル&内容が流れてきた時はモーダルを表示。空の場合は非表示
this.subscription = this.modalService.subject.subscribe((next) => {
if (next) {
this.active = true;
this.title = next.title;
this.body = next.body;
} else {
this.active = false;
this.title = '';
this.body = '';
}
});
}
ngOnInit(): void {}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
closeModal() {
this.modalService.closeModal();
}
}
3. モーダル呼び出し側の作成
src/app/pages/about.component.html
<button (click)="openModal1()">モーダルを開く1</button>
<button (click)="openModal2()">モーダルを開く2</button>
<button (click)="openModal3()">モーダルを開く3</button>
src/app/pages/about.component.ts
import { Component, OnInit } from '@angular/core';
import { ModalService } from 'src/app/services/modal.service';
@Component({
selector: 'app-about',
templateUrl: './about.component.html',
styleUrls: ['./about.component.scss'],
})
export class AboutComponent implements OnInit {
constructor(private modalService: ModalService) {}
ngOnInit(): void {}
// モーダルを表示したい場合はモダールサービスのopenModalメソッドを呼び出すだけ!
openModal1() {
this.modalService.openModal('タイトル1', '内容1');
}
openModal2() {
this.modalService.openModal('タイトル2', '内容2');
}
openModal3() {
this.modalService.openModal('タイトル3', '内容3');
}
}