きなこもち.net

.NET Framework × UiPath,Orchestrator × Azure × AWS × SIer

Angular Material × mat-selection-listとdialogの実装 × メモ

この記事の目的

この記事は、
Angular MaterialのSelection Listに初期設定を追加するための実装メモ
です。

本題

やりたいこと

ある画面があります。
f:id:kinakomotitti:20191006030945p:plain

Open Dialogボタンを押下したら、Selection Listが配置されたダイアログが表示されます。
この時、元の画面で選択されていた名前があらかじめチェックされた状態で表示されます。
f:id:kinakomotitti:20191006031001p:plain

選択を変更し、ダイアログを閉じたら・・・
f:id:kinakomotitti:20191006031010p:plain

選択されている値が変更されます。
f:id:kinakomotitti:20191006031021p:plain


そんな感じです。
開発環境は以下の通りです。

C:\>npm -v
6.9.0


C:\>ng --version
Angular CLI: 8.3.2
Node: 10.16.3
OS: win32 x64
Angular:
Package Version

@angular-devkit/architect 0.803.2
@angular-devkit/core 8.3.2
@angular-devkit/schematics 8.3.2
@schematics/angular 8.3.2
@schematics/update 0.803.2
rxjs 6.4.0

今回作ったコードは以下のGitHubに登録しています。
github.com

dialog.htmlの実装

dialogに表示する情報を格納するためのクラスを定義します。今回は、簡単に名前と年齢を格納できるPOCOを用意します。

export class DialogData {
  name: string;
  age: number;
}

DialogDataクラスの配列をDialogに渡したいですが、これではどのDialogDataが選択されているか判断がつかないので、このクラスをさらにラップしたクラスを用意します。

export class DialogData2 {
  info: DialogData;
  selected: boolean; // <- この値を見てListのチェックの有無を決める
}


DialogDataクラスは、Dialogの呼び出し元画面とのデータのやり取りに利用し、DialogData2クラスは、Dialog画面に表示するための情報として利用します。ということで、Dialog画面のHTML定義は以下のようになります。

<mat-selection-list #shoes >
    <mat-list-option *ngFor="let shoe of typesOfShoes" [value]="shoe.info" [selected]="shoe.selected">
        {{shoe.info.name}}, {{shoe.info.age}}
    </mat-list-option>
</mat-selection-list>

<button mat-button [mat-dialog-close]="shoes.selectedOptions.selected" cdkFocusInitial>Ok</button>

Sampleそのまま引用しているのでShoesという不適切な名前がついていますが、気にせず進めますw

ここでは、mat-list-optionのSelected属性にDialogData2のSelectedプロパティをバインドし、その値に応じてチェックの有無を決めるようにしています。

そのため、コンストラクタや、何かのイベント発生時に呼ばれるメソッドから、DialogData2のSelectedプロパティを変更することでチェックの有無を操作することができるようになります。

Dialog画面に表示しているtypesOfShoesプロパティは、DBから取得したマスターデータのようなものをイメージしています。なので、typesOfShoesに格納されたDialogDataのリストの中に、Dialogの呼び出し元画面から渡ってきたDialogDataが存在したとき、チェックがTrueとして表示されます。

この一連の実装はこんな感じで行っています。

export class DialogSample {
   //※ほんとは、DBから値を取得してくるイメージなのですが、簡単のため直打ちしています
  typesOfShoes: DialogData2[] = [
    { info: { name: "Boots", age: 11 }, selected: false },
    { info: { name: "Clogs", age: 11 }, selected: false },
    { info: { name: "Loafers", age: 11 }, selected: false },
    { info: { name: "Moccasins", age: 11 }, selected: false }
  ];

  constructor(
    public dialogRef: MatDialogRef<DialogData>,
    @Inject(MAT_DIALOG_DATA) public data: DialogData[]) {
    this.typesOfShoes.forEach(item => {
      this.data.forEach(element => {
        if (element.name === item.info.name) {
          item.selected = true; //<- ここでTrueにしている
        }
      });
    });
}}

まとめ

  • mat-list-option の[selected]属性で、チェックの有無を操作できる。
  • Dialog呼び出し元と呼び出し先とのデータの連携は、MAT_DIALOG_DATAを利用する。