君は心理学者なのか?

大学時代に心理学を専攻しなぜかプログラマになった、サイコ(心理学)プログラマかろてんの雑記。

Angular2/4にてbootstrapのmodalウィンドウを開き、閉じた時に親コンポーネントに値を反映させる

Angular2/4を使ってmodalウィンドウを表示する

bootstrap標準のmodalウィンドウを、

Angularから開こうと頑張った話です。

bootstrapとAngular以外は使っておりません。

0. 準備

0-1. プロジェクトの作成

新規プロジェクトを作成し、サーバをスタートさせます。

ng new modal
ng serve

0-2. ngx-bootstrapのパッケージをinstall

npm install ngx-bootstrap --save

0-3. 必要なmoduleを読み込む

// app.module.ts
import { FormsModule } from '@angular/forms'; // 追加
import { ModalModule } from 'ngx-bootstrap'; // 追加

0-4. 必要なmoduleをimportする

@NgModule({
  imports: [
    ModalModule.forRoot(), // 追加
    FormsModule // 追加
  ],  
})

0-5. bootstrap.min.cssを読み込む

<!-- index.html -->
...
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
...

1. ダイアログコンポーネントの作成と編集

1-1. ダイアログコンポーネントの作成

ng g component dialog

1-2. dialog.component.htmlを編集

<!-- dialog.component.html -->
<div class="modal fade" bsModal #lgModal="bs-modal" id="sampleModal" tabindex="-1">
  <div class="modal-dialog modal-sm">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" (click)="lgModal.hide()"><span>×</span></button>
        <h4 class="modal-title">テスト</h4>
      </div>
      <div class="modal-body">
        <input type="text" [(ngModel)]="dialogData">
      </div>
      <div class="modal-footer">   
        <button type="button" class="btn btn-default" (click)="lgModal.hide()" data-dismiss="modal">キャンセル</button>
        <button type="button" class="btn btn-info" (click)="onClose()" data-dismiss="modal">決定</button>
      </div>
    </div>
  </div>
</div>

1-3. dialog.component.tsを編集

import {
  Component,
  OnInit,
  ViewChild,
  Input,
  Output,  
  EventEmitter
} from '@angular/core';
import {ModalDirective} from "ngx-bootstrap";

export class DialogComponent implements OnInit {
  /** modal要素を取得 */
  @ViewChild("lgModal") modalRef :ModalDirective;
  /** 親からdialogDataを受け取る */
  @Input() dialogData;
  /** 親へのイベント通知用 */
  @Output() clickCloseButton = new EventEmitter<any>();

  /** modal内で扱うデータ */
  public data;
...
  /** 親コンポーネントから呼び出される */
  openDialog()
  {
    /** ダイアログを開いた時、親データから値を取り直す */
    this.data = this.dialogData;
    this.modalRef.show();
  }

  /** モーダルの閉じるボタンを押した時に呼び出される */
  onClose()
  {
    this.modalRef.hide();
    /** 親コンポーネントへイベントを通知 */
    this.clickCloseButton.emit({data: this.dialogData});
  }
}

2. appコンポーネントの編集

2-1. app.component.htmlを編集

<!-- app.component.html -->
{{parentData}}
<button (click)="openDialog()" class="btn btn-primary">ダイアログを開く</button>
<!-- ダイアログコンポーネント -->
<app-dialog [dialogData]="parentData" (clickCloseButton)="getDialogData($event)" #dialog></app-dialog>

コンポーネントから、

子であるダイアログコンポーネントにparentDataをわたしています。

また、

コンポーネントから親コンポーネントにclickCloseというイベントをemitし、

getDialogDataという関数で受け取っています。

2-2. app.component.tsを編集

import {
  Component,
  ViewChild // 追加
} from '@angular/core';
import { DialogComponent } from './dialog/dialog.component'; // 追加

  /** ここで子コンポーネントであるダイアログコンポーネントを取得しています */
  @ViewChild("dialog") dialogComponent: DialogComponent;
  parentData :string = "hello";

  openDialog() {
    this.dialogComponent.openDialog();
  }

  getDialogData(e)
  {
    /** 親コンポーネントのデータ書き換えを行います */
    this.parentData = e.data;
  }

結果

f:id:karoten512:20171206193533g:plain

参考

【AngularでModal設定】Angular2でダイアログを開く方法 | 思いのままを綴る

お世話になりました。

ソースコード

github.com