MaterialDesign
Angular4

Angular 4 マテリアルデザインのダイアログ

今日は、マテリアルデザインのダイアログを初めて触って最初動かなかったので、メモとして残しておく。やりたいことは、何かを登録したら、登録しました!とダイアログを出して、画面遷移したいという簡単なもの。

ハマりポイントは一箇所だけ。

基本このままだけど、ドキュメントが古い。MdxxxMatxxx に置き換えて参照すること。だから、ダイアログを出したいところに、こんな感じで書けばいいでしょう。

動くと思われたコード

あとは、必要なタイミングで、openDialog() を呼び出したらいいだけなんちゃう?

xxxx.ts

import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material';
import { Router } from '@angular/router';
 :

export class xxxComponent {
  constructor(public dialog:MatDialog, private router:Router) {}
    openDialog(): void {
    let dialogRef = this.dialog.open(ConfirmDialog, {
      width: '400px',
      height: '215px',
      data: {name: this.car.name}
    });

    dialogRef.afterClosed().subscribe(result => {
      console.log("The dialog was closed");
      this.router.navigate(['/dashboard']);
    })
  }
}

@Component({
  selector: 'confirm-dialog',
  template: `
  <h2 mat-dialog-title>Success</h2>
  <mat-dialog-content>
  <p>Thank you for uploading!</p>
  <p>{{data.name}} is waiting for evaluation</p>
  </mat-dialog-content>
  <mat-dialog-actions>
    <button mat-button [mat-dialog-close]="true">Close</button>
  </mat-dialog-actions>
  `
})
export class ConfirmDialog {
     constructor(
      public dialogRef: MatDialogRef<ConfirmDialog>,
      @Inject(MAT_DIALOG_DATA) public data: any) {}

      onClick(): void {
        this.dialogRef.close();
      }
}

material.module.ts

import { NgModule } from '@angular/core';

import {
  MatMenuModule,
  MatToolbarModule,
  MatIconModule,
  MatTabsModule,
  MatCardModule,
  MatGridListModule,
  MatButtonModule,
  MatInputModule,
  MatDialogModule,   <- 追加
} from '@angular/material';

@NgModule({
  imports: [
    MatMenuModule,
    MatToolbarModule,
    MatIconModule,
    MatTabsModule,
    MatCardModule,
    MatGridListModule,
    MatButtonModule,
    MatInputModule,
    MatDialogModule <- 追加
  ],
  exports: [
    MatMenuModule,
    MatToolbarModule,
    MatIconModule,
    MatTabsModule,
    MatCardModule,
    MatGridListModule,
    MatButtonModule,
    MatInputModule,
    MatDialogModule <- 追加
  ]
})
export class MaterialModule {}

しかし、実際は動かない。entryComponents に足すの忘れてない?的なエラーがでる。
で、entryComponentsって何よ?

entryComponents を設定する

The entryComponents array is used to define only components that are not found in html and created dynamically with ComponentFactoryResolver. Angular needs this hint to find them and compile. All other components should just be listed in the declarations array.

つまり、entryComponents に登録するものは、HTML には出てこないが、ダイナミックに作成されるもの。まさにダイアログはそれだね。app.module.ts に追加すると良い

app.module.ts

@NgModule({
  declarations: [
    AppComponent,
    CarDetailComponent,
    DashboardComponent,
    ConfirmDialog   <- 追加した
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    MaterialModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    ImageUploadModule.forRoot(),
  ],
  entryComponents: [ <- 追加した
    ConfirmDialog
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

無事、しっかりとダイアログがオープンした。 

ダイアログへの値の引き渡し

他のポイントとしては、ダイアログに何か情報を引き渡したいときはつぎのようにしてあげると良い

html

  <p>{{data.name}} is waiting for evaluation</p>

xxxx.ts

    openDialog(): void {
    let dialogRef = this.dialog.open(ConfirmDialog, {
      width: '400px',
      height: '215px',
      data: {name: this.car.name}
    });

簡単でした。