【Angular6】ngx-simple-modalでモーダルのコンポーネントを作成してみた
はじめに
どうも、福岡のmeです。
今回はAngular6環境でモーダルを作成していました。
普段はBootstrapで作ってしまうのですが、HTMLファイルの中に複数のモーダルを埋めるのはあまりスマートではないと思い
ngx-simple-modal
というモジュールを使ってコンポーネント化してみたところ、シンプルに実装できたのでご紹介したいと思います。
やりたかったこと
- シンプルなモーダルの表示
- モーダル内で行う処理をコンポーネント化したい
- ページ内にコンポーネントとして埋め込みたい
- 複数のモーダルをHTMLファイルにつらつらと書きたくない
Outcome
環境
Angular環境は以下の通りです。
Angular CLI: 6.0.8 Node: 8.11.2 OS: darwin x64 Angular: 6.0.7 ... animations, common, compiler, compiler-cli, core, forms ... http, language-service, platform-browser ... platform-browser-dynamic, router Package Version ----------------------------------------------------------- @angular-devkit/architect 0.6.8 @angular-devkit/build-angular 0.6.8 @angular-devkit/build-optimizer 0.6.8 @angular-devkit/core 0.6.8 @angular-devkit/schematics 0.6.8 @angular/cdk 6.3.1-825d35c @angular/cli 6.0.8 @angular/flex-layout 6.0.0-beta.16 @angular/material 6.2.1 @ngtools/webpack 6.0.8 @schematics/angular 0.6.8 @schematics/update 0.6.8 rxjs 6.2.1 typescript 2.7.2 webpack 4.8.3
インストール
npmを使います。
npm install ngx-simple-modal
コンポーネントの作成
modal.component.tsファイルを作成し、HTMLテンプレートとjs処理を書きます。
import { Component } from '@angular/core'; import { SimpleModalComponent } from 'ngx-simple-modal'; export interface ConfirmModel { title: string; message: string; } @Component({ selector: 'confirm', template: ` <div class="modal-content"> <div class="modal-header"> <h4>{{title || 'Confirm'}}</h4> </div> <div class="modal-body"> <p>{{message || 'Are you sure?'}}</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" (click)="confirm()">はい</button> <button type="button" class="btn btn-outline-danger" (click)="cancel()">いいえ</button> </div> </div> ` }) export class ConfirmComponent extends SimpleModalComponent<ConfirmModel, boolean> implements ConfirmModel { title: string; message: string; constructor() { super(); } confirm() { // on click on confirm button we set dialog result as true, // ten we can get dialog result from caller code this.result = true; this.close(); } cancel() { this.result = false; this.close(); } }
app.module.ts にngx-simple-modalモジュールと上で作成したコンポーネントをインポートします。
import { NgModule} from '@angular/core'; import { CommonModule } from "@angular/common"; import { BrowserModule } from '@angular/platform-browser'; import { SimpleModalModule } from 'ngx-simple-modal'; import { ConfirmComponent } from './modal.component'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ CommonModule, BrowserModule, SimpleModalModule ], bootstrap: [AppComponent], entryComponents: [ConfirmComponent] }) export class AppModule {}
作成したモーダルのコンポーネントをentryComponentsに追加するのも忘れずに。
挿入したいコンポーネントに追加
上で作成したモーダルをコンポーネントに追加し、呼び出す処理を書きます。
import { Component } from '@angular/core'; import { Observable } from 'rxjs/Rx'; import { SimpleModalService } from 'ngx-simple-modal'; import { ConfirmComponent } from './modal.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(private SimpleModalService: SimpleModalService) {} confirmResult = null; showConfirm() { this.SimpleModalService.addModal(ConfirmComponent, { title: '確認', message: 'どうしますか?'}) .subscribe((isConfirmed) => { // Get modal result this.confirmResult = isConfirmed; }); } }
あとはHTMLから
showConfirm()
を呼び出すだけです。
<div class="row"> <div class="col-sm-4 text-right"> <b>シンプルなモーダル: </b> </div> <div class="col-sm-4"> <button class="btn btn-default btn-block" (click)=showConfirm()>確認する</button> </div> <div class="col-sm-4" *ngIf="confirmResult != null"> <span>返答: </span> <b [ngClass]="{'text-danger': !confirmResult, 'text-success': confirmResult}">{{confirmResult ? 'はい': 'いいえ'}}</b> </div> </div>
スタイリング
ngx-simple-modalにはデフォルトのcssをつけることが出来ます。
そのまま利用したい場合はangular.json内でcssを定義します。
"styles": [ "styles.css", "../node_modules/ngx-simple-modal/styles/simple-modal.css" ],
まとめ
いかがだったでしょうか。モーダルはHTMLとBootstrapを使えば簡単に作成できますが、
ページにhtmlで書いてしまうと数が増えた時にメンテがしづらくなったり、どのモーダルが何の処理をしているのか読み解きづらくなりがちですよね。
今回はコンポーネント化してしまうことで、よりシンプルに書くことができました。
公式のドキュメントにはもっと色々な使い方を紹介しているので、興味がある方はぜひ参考にしてみてください。