はじめに
ずっとないと思い込んでいたけど.....モーダルとトースト普通にあるんすね、Angular Material 。
ということでCSSフレームワークのAngular Materialを使ってモーダルとトーストを実装していきます
環境
本記事における実行環境と使用ライブラリについて
$ ng version
Angular CLI: 8.3.20
Node: 12.13.1
OS: darwin x64
Angular: 8.2.14
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.803.20
@angular-devkit/build-angular 0.803.20
@angular-devkit/build-optimizer 0.803.20
@angular-devkit/build-webpack 0.803.20
@angular-devkit/core 8.3.20
@angular-devkit/schematics 8.3.20
@angular/cdk 7.3.7
@angular/cli 8.3.20
@angular/fire 5.2.3
@angular/material 7.3.7
@ngtools/webpack 8.3.20
@schematics/angular 8.3.20
@schematics/update 0.803.20
rxjs 6.5.3
typescript 3.5.3
webpack 4.39.2
実装
作成中のメモアプリにAngular Materialを使用して、下記2点の機能を実装します。
モーダル
Angular MaterialのDialog を使って、
リンクをクリックするとモーダルでフォルダの新規作成のフォームを表示する機能を作成します。
新規フォルダ リンクをクリックすると...
フォルダ作成モーダルが表示される
AppModuleの設定1
モーダルを使用する事前準備として、AppModuleのimports:[]
にMatDialogModule
を追加します。
import { MatDialogModule } from '@angular/material/dialog' ;
@NgModule ( {
imports: [
MatDialogModule,
] ,
bootstrap: [ AppComponent]
} )
export class AppModule {}
モーダルのコンポーネントを作成
モーダルのコンポーネントを作成していきます。
まずは、コンポーネントクラスのファイルを作成します。
src/app/component/folder-create-modal/folder-create-modal.component.ts
import { Component, OnInit } from '@angular/core' ;
import { MatDialogRef } from '@angular/material/dialog' ;
@class FolderCreateModalComponent
@Component ( {
selector: 'app-folder-create-modal' ,
templateUrl: './folder-create-modal.component.html' ,
styleUrls: [ './folder-create-modal.component.scss' ]
} )
export class FolderCreateModalComponent implements OnInit {
constructor(public dialogRef: MatDialogRef< FolderCreateModalComponent>) {}
ngOnInit() {}
public onOkClick() : void {
this .dialogRef.close ();
TODO
}
public onNoClick() : void {
this .dialogRef.close ();
}
}
constructor(public dialogRef: MatDialogRef<FolderCreateModalComponent>) {}
でモーダルへの参照変数をDIしています。このモーダルへの参照変数を使用して、ボタン押下時にモーダルを閉じる処理を実装しています。
続いて、モーダルのテンプレートファイル(HTML)です。
mat-dialog-actions align="end"
でモーダルに表示するボタンを右寄せにしています。
src/app/component/folder-create-modal/folder-create-modal.component.html
< h1 mat-dialog- title > 新規フォルダを作成</ h1 >
< div mat-dialog- content >
< p > フォルダは、同じテーマや目的をもつメモをまとめて整理するのに役立ちます。</ p >
< mat-form -field class = "folder" >
< input matInput class = "title" placeholder= "名前" />
</ mat-form -field>
</ div >
< div mat-dialog-actions align = "end" >
< button mat-button (click)= "onNoClick()" > キャンセル</ button >
< button mat-button cdkFocusInitial (click)= "onOkClick()" > 作成</ button >
</ div >
モーダルのレイアウトを設定しているSCSSファイルです。特に特記事項がないため、このファイルについては説明をスキップします。
src/app/component/folder-create-modal/folder-create-modal.component.scss
. folder {
width : 100 %;
}
モーダルを表示する側の実装
モーダルを表示するリンクを実装するコンポーネントを作成します。
src/app/component/forder-list-header/forder-list-header.component.ts
import { MatDialog } from '@angular/material/dialog' ;
export class ForderListHeaderComponent implements OnInit {
constructor(public dialog: MatDialog) {}
public create() {
console.log( 'create' );
const dialogRef = this .dialog.open ( FolderCreateModalComponent, {
width: '360px'
} );
dialogRef.afterClosed() .subscribe(() => {
console.log( 'The dialog was closed' );
} );
}
}
フォルダ新規作成リンクをクリックした時にcreate()
メソッドを呼び出して、Dialogのopen
でモーダルを表示しています。
なお、モーダルを表示する機能を実装しているコンポーネントであるため、constructor
でMatDialog
をDIする必要があります。
モーダルを表示する側のコンポーネントのテンプレートファイルです。新規フォルダリンクを実装しています。
src/app/component/forder-list-header/forder-list-header.component.html
< div class = "header" >
< div class = "title" > フォルダ</ div >
< a (click)= "create()" class = "add-link" >
< mat-icon class = "icon" > create_new_folder</ mat-icon>
< span > 新規フォルダ</ span >
</ a >
</ div >
AppModuleの設定2
最後に、AppModuleのentryComponents:[]
に今回作成したモーダルのコンポーネントであるFolderCreateModalComponent
を追加してモーダルの実装は完了です。
import { FolderCreateModalComponent } from './component/folder-create-modal/folder-create-modal.component' ;
@NgModule ( {
entryComponents: [ FolderCreateModalComponent] ,
} )
export class AppModule {}
トースト
Angular MaterialのSnackbar を使って、
ログアウトが成功した時にログアウトが完了した旨をトーストでユーザーに知らせる機能を作成します。
ログアウトに成功した旨をトーストで知らせる
AppModuleの設定
モーダルを使用する事前準備として、AppModuleのimports:[]
にMatSnackBarModule
を追加します。
import { MatSnackBarModule } from '@angular/material/snack-bar' ;
@NgModule ( {
imports: [
MatSnackBarModule
] ,
} )
export class AppModule {}
トースト用のサービスクラスを作成
トーストを表示するためのサービスクラスを作成します。もちろんサービスを作成せずにトーストを表示したいコンポーネントに直接処理を描いても問題ありません。
src/app/services/toast.service.ts
import { Injectable } from '@angular/core' ;
import { MatSnackBar } from '@angular/material/snack-bar' ;
@class ToastService
@Injectable ( {
providedIn: 'root'
} )
export class ToastService {
private _actionMessage = 'Close' ;
constructor(private _snackBar: MatSnackBar) {}
@param {string}
public open( message: string ) : void {
this ._snackBar.open ( message, this ._actionMessage, {
duration: 2000
} );
}
}
open
メソッドでトーストを表示しています。なお、MatSnackBar
をDIする必要があります。
サービスクラスを経由してトーストを表示
最後に作成したToastService
をトーストを表示したいコンポーネントで呼び出す処理を書いてあげれば完了です。
src/app/component/header/header.component.ts
import { ToastService } from '../../services/toast.service' ;
export class HeaderComponent implements OnInit {
constructor(
public afAuth: AngularFireAuth,
private router: Router,
private _toastService: ToastService,
private spinnerService: SpinnerService
) {}
public signOut() : void {
this .spinnerService.show();
this .afAuth.auth
.signOut()
.then(() => {
this .router.navigate( [ '/login' ] );
this ._toastService.open ( 'ログアウトしました。' );
} )
.catch ( error => {
this ._toastService.open ( 'ログアウトに失敗しました。' );
console.log( error);
} )
.finally (() => this .spinnerService.hide());
}
}