【Angular6】ngx-simple-modalでモーダルのコンポーネントを作成してみた

2018.07.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

どうも、福岡の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処理を書きます。

`modal.component.ts`

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モジュールと上で作成したコンポーネントをインポートします。

`app.module.ts`

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に追加するのも忘れずに。

挿入したいコンポーネントに追加

上で作成したモーダルをコンポーネントに追加し、呼び出す処理を書きます。

`app.component.ts`

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()

を呼び出すだけです。

`app.component.html`

  <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を定義します。

`angular.json`

"styles": [
  "styles.css",
  "../node_modules/ngx-simple-modal/styles/simple-modal.css"
],

まとめ

いかがだったでしょうか。モーダルはHTMLとBootstrapを使えば簡単に作成できますが、 ページにhtmlで書いてしまうと数が増えた時にメンテがしづらくなったり、どのモーダルが何の処理をしているのか読み解きづらくなりがちですよね。

今回はコンポーネント化してしまうことで、よりシンプルに書くことができました。
公式のドキュメントにはもっと色々な使い方を紹介しているので、興味がある方はぜひ参考にしてみてください。

stackblitzでのデモ

Ngx-simple-modal