今回はAngularのmat-tableに編集ボタンを付けて、編集ボタンからダイアログを開くとダイアログが開き、フォームに入力した情報がテーブルに反映される、というような機能を実装していきたいと思います。
MattableとMatDialogの導入方法については以下の記事で解説しているので、まずそちらを参考にしてください。
【Angular】ダイアログ画面をMat-dialogで実装する
AngularによるWebアプリ開発⑧~Mat-Tableでテーブルを作成する
# コンポーネントを作成する $ ng generate component edit-table-sample $ ng generate component edit-dialog
<app-routing.module.ts>
import { NgModule } from "@angular/core"; import { Routes, RouterModule } from "@angular/router"; ~~~~ ~~~~ import { EditTableSampleComponent } from "./edit-table-sample/edit-table-sample.component"; //これを追加する! const routes: Routes = [ { path: "edit-mattable-sample", component: EditTableSampleComponent }, //これを追加! ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) export class AppRoutingModule {}
import { BrowserModule } from "@angular/platform-browser"; import { NgModule } from "@angular/core"; import { AppRoutingModule } from "./app-routing.module"; import { AppComponent } from "./app.component"; ~~~~ ~~~~ import { EditTableSampleComponent } from "./edit-table-sample/edit-table-sample.component"; //これを追加 import { EditDialogComponent } from "./edit-dialog/edit-dialog.component"; //これを追加 @NgModule({ declarations: [ AppComponent, ~~~~ EditTableSampleComponent, //これを追加 EditDialogComponent,//これを追加 ], imports: [ ], providers: [], entryComponents: [EditDialogComponent],//これを追加 }) export class AppModule {}
<edit-table-sample.component.html>
<div style='padding:20px;'> <table mat-table [dataSource]="dataSource" #mytable class="my-table mat-elevation-z8"> <!-- Id Column --> <ng-container matColumnDef="id"> <th mat-header-cell *matHeaderCellDef> ID. </th> <td mat-cell *matCellDef="let element"> {{element.id}} </td> </ng-container> <!-- Name Column --> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef> 名前 </th> <td mat-cell *matCellDef="let element"> {{element.name}} </td> </ng-container> <!-- Action Column --> <ng-container matColumnDef="action"> <th mat-header-cell *matHeaderCellDef> アクション </th> <td mat-cell *matCellDef="let element" class="action-link"> <a (click)="openDialog('更新',element)"><button mat-raised-button color='primary'>編集</button></a> <a (click)="openDialog('削除',element)"><button mat-raised-button>削除</button></a> </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table> <br /><br /> <button mat-button (click)="openDialog('Add',{})" mat-flat-button color="primary">列を追加する</button> </div>
<edit-table-sample.component.ts>
import { Component, OnInit, ViewChild } from "@angular/core"; import { MatDialog, MatTable } from "@angular/material"; import { EditDialogComponent } from "../edit-dialog/edit-dialog.component"; export interface UsersData { name: string; id: number; } const ELEMENT_DATA: UsersData[] = [ { id: 1560608769632, name: "Artificial Intelligence" }, { id: 1560608796014, name: "Machine Learning" }, { id: 1560608787815, name: "Robotic Process Automation" }, { id: 1560608805101, name: "Blockchain" }, ]; @Component({ selector: "app-edit-table-sample", templateUrl: "./edit-table-sample.component.html", styleUrls: ["./edit-table-sample.component.css"], }) export class EditTableSampleComponent implements OnInit { ngOnInit() {} displayedColumns: string[] = ["id", "name", "action"]; dataSource = ELEMENT_DATA; @ViewChild(MatTable, { static: true }) table: MatTable; constructor(public dialog: MatDialog) {} openDialog(action, obj) { obj.action = action; const dialogRef = this.dialog.open(EditDialogComponent, { width: "250px", data: obj, }); dialogRef.afterClosed().subscribe((result) => { if (result.event == "Add") { this.addRowData(result.data); } else if (result.event == "更新") { this.updateRowData(result.data); } else if (result.event == "削除") { this.deleteRowData(result.data); } }); } addRowData(row_obj) { var d = new Date(); this.dataSource.push({ id: d.getTime(), name: row_obj.name, }); this.table.renderRows(); } updateRowData(row_obj) { this.dataSource = this.dataSource.filter((value, key) => { if (value.id == row_obj.id) { value.name = row_obj.name; } return true; }); } deleteRowData(row_obj) { this.dataSource = this.dataSource.filter((value, key) => { return value.id != row_obj.id; }); } }
<edit-dialog.component.ts>
import { Component, OnInit, Inject, Optional } from "@angular/core"; import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material"; export interface UsersData { name: string; id: number; } @Component({ selector: "app-edit-dialog", templateUrl: "./edit-dialog.component.html", styleUrls: ["./edit-dialog.component.css"], }) export class EditDialogComponent implements OnInit { action: string; local_data: any; constructor( public dialogRef: MatDialogRef, //@Optional() is used to prevent error if no data is passed @Optional() @Inject(MAT_DIALOG_DATA) public data: UsersData ) { console.log(data); this.local_data = { ...data }; this.action = this.local_data.action; } doAction() { this.dialogRef.close({ event: this.action, data: this.local_data }); } closeDialog() { this.dialogRef.close({ event: "Cancel" }); } ngOnInit() {} }
<edit-dialog.component.html>
<h1 mat-dialog-title>アクション: <strong>{{action}}</strong></h1> <div mat-dialog-content> <mat-form-field *ngIf="action != 'Delete'; else elseTemplate"> <input placeholder="{{action}} Name" matInput [(ngModel)]="local_data.name"> </mat-form-field> <ng-template #elseTemplate> 本当に削除しますか? <b>{{local_data.name}}</b>? </ng-template> </div> <div mat-dialog-actions> <button mat-button (click)="doAction()" mat-flat-button color="primary">{{action}}</button> <button mat-button (click)="closeDialog()">キャンセル</button> </div>
以上のコードを追記した状態でhttp://localhost:4200/edit-mattable-sampleにアクセスすると以下のような状態になっています。
そして、各ボタンをクリックすると以下のようにダイアログが表示されデータを編集・削除することができます。
【Githubのサンプルコード】
参照:https://www.freakyjolly.com/angular-material-table-operations-using-dialog/#.XtFZ52j7THo
関連記事:【Angular】Mat-Tableでヘッダーが複数行になるテーブルを作ってみる
関連記事:【Angular】Mattableの各ヘッダー列の幅を画面幅に合わせて自動調整する
関連記事:AngularによるWebアプリ開発⑧~Mat-Tableでテーブルを作成する
コメント