angular materialを使用して簡単なプログラムを作成してみました。都道府県のリストデータをCRUDするプログラムの作例です。殆どがAngular MaterialのExampleベースのコードですが、自分の思うよう動作をさせるにあたり、調査・コーディングした部分も有るのでブログに載せてみます。
※DB連動していないため、追加変更したデータは保持されません。
Angular MaterialのStart upに従いプロジェクトを作成し、各コンポーネントの利用方法はExampleを参考にしています。ソースはstackblitzにアップしてあり、動作確認可能です。
##環境
Angular CLI: 7.0.7
Node: 8.11.4
OS: windows8.1 x64
Angular: 7.0.4
Package Version
@angular-devkit/core 7.0.7
@angular-devkit/schematics 7.0.7
@angular/cdk 7.1.1
@angular/cli 7.0.7
@angular/material 7.1.1
@ngtools/webpack 7.0.7
@schematics/angular 7.0.7
@schematics/update 0.10.7
rxjs 6.3.3
typescript 3.1.6
webpack 4.19.1
使用したmaterialコンポーネントは以下です。
BrowserAnimationsModule
MatInputModule
MatButtonModule
MatTableModule
MatCheckboxModule
MatDialogModule
MatPaginatorModule
MatSortModule
MatSelectModule
#アプリケーションコンポーネント
コンポーネント/サービス | 説明 | material |
---|---|---|
PrefViewComponent | table表示,選択,フィルター,ソート,ページング | MatTableModule,MatCheckboxModule,MatPaginatorModule,MatSortModule,MatSelectModule |
PrefViewEditComponent | 編集ボタン,Dialog呼出,データ削除 | MatButtonModule,MatDialogModule |
PrefViewEditDialogComponent | Dialog表示,データ追加・更新 | MatDialogModule,MatInputModule,MatButtonModule |
prefService | データ保持,コンポーネント連携 |
以下アプリケーションコンポーネントのポイント部分のみ、抜粋して説明します。
PrefViewComponent
単一行選択の実装
matCheckBoxがバインドしているSelectionModelの生成にて、コンストラクタ第一引数(選択モード指定)に単一(false)を指定します。
selection = new SelectionModel<PrefItem>(false,[]);
checkBox変更のイベントをリスニングするため、同SelectionModelのエミッターを宣言してsubscribeにコールバック関数を設定します。
private cbEmmiter=this.selection.onChange.asObservable();
ngOnInit() {
this.cbEmmiter.subscribe(cb=>{
if(cb.source.selected.length > 0){
this.service.selectPerfItem=cb.source.selected[0];
}else{
this.service.selectPerfItem=null;
}
});
}
#####列ソート ページング
MatSort, MatPaginatorを使用することで簡単に実装できます。実装方法はExampleの通りです。作例ではtableのdatasourceが非同期に更新されるので、その契機で同コンポーネントを再バインドする必要があります。該当の処理をngAfterViewInitに書きます。
ngAfterViewInit(){
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
また、datasourceバインドの契機にも同処理を書いておきます。
updateData(){
//tableのデータソース更新
this.dataSource= new MatTableDataSource<PrefItem>(this.service.data);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
#####フィルター
Exampleをそのまま流用です。MatTableDataSourceのfilterメソッドを使用しています。
PrefViewEditDialogComponent
親コンポーネントと切り離れた方が可読性が良いと思い、独立コンポーネントとして実装ました。これにより1つのコンポーネントに縛られることなく、複数のコンポーネントで共有することができます。サービスから動作モードを取得して、追加・更新ダイアログを共通にしています。
MatInputの数値表示をカンマ区切りとしたいため、changeイベントで変換をかけています。
onChangeArea(){
this.editItem$.prefArea=Number(this.perfArea$.replace(/,/g,''));
this.perfArea$=formatNumber(this.editItem$.prefArea,this.locale,'.2');
}
Dialog上でデータの追加・更新を処理しており、処理後の通知をサービスのObservableに流しています。他コンポーネントはサービスのObservableをsubscribeすることで変更通知を受信することができます。この仕組みによってtableコンポーネントは表示を更新します。
#最後に
materialを使ってみた感触ですが、あまり突っかかることなく使えました(気持ち良く使える)。特に気に入っているところはDialogの使いやすさです。コンポーネント化すれば、どのコンポーネントからも呼べるし、別途作成したコンポーネントをDialog上に配置することもできます。疎結合デザインのメリットを実感できるUIですね。