Angular Materialを使って、ログイン用のフォームを作ります
Angular Materialのインストールから解説している記事はこちら
バージョン情報
Angular: 5.2.9
Node: 8.1.4
@angular/material: 5.2.4
テンプレート駆動型とモデル駆動型
Angularのフォームには、テンプレート駆動型とモデル駆動型があります
テンプレート駆動型のフォーム
- 検証ルールをテンプレート側に記述する
- モデル駆動型よりも手軽に実装できる
- 複雑な要件には向いていない
NgModule
にFormsModule
のインポートが必要
モデル駆動型のフォーム
- 検証ルールをコンポーネント側に記述する
- コードが冗長になりやすい
- 複雑な要件でも表現できる
NgModule
にReactiveFormsModule
のインポートが必要
今回は、簡単に書けそうなテンプレート駆動型のフォームを採用します。ただ、Angular Materialで作られたフォームのサンプルを見ると、モデル駆動型のフォームで記述されているものが多い気がするので、後々問題が発生したら、モデル駆動型に切り替えます。
NgModuleの設定
ログインフォーム作成のために、下記のAngular Materialコンポーネントを使ったので、NgModuleに設定していきます。
MatButtonModule
MatCardModule
MatInputModule
MatFormFieldModule
MatIconModule
また、今回はAngularのテンプレート駆動型のフォームを使うので、FormsModule
の設定も必要です。
src/app/app.module.ts
:
import { FormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatInputModule } from '@angular/material/input'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; @NgModule({ declarations: [AppComponent, ExchangeListComponent, PrivateComponent], imports: [ // add this! MatButtonModule, MatCardModule, MatInputModule, MatFormFieldModule, MatIconModule, FormsModule, // ...省略 ], // ...省略
下記の手順を実行してください
上記のモジュール(
MatFormFieldModule
他6つ)をインポート@NgModule
デコレータで定義されているimports:[]
リストに上記の6つのモジュールを追加する
index.htmlにアイコンのCDNを追加
マテリアルアイコンをパスワード欄で使うので、下記のCDNをindex.htmlに追加する必要があります。
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
src/app/index.html
:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>CriptocurrencyApiCall</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> </head> <body> <app-root></app-root> </body> </html>
ログインフォームを作る
下記の要件に従って、ログインフォームを作ります。
- ログインフォームの要件
- API Key欄とAPI Secret欄がある
- API Secret欄は、目のアイコンをクリックすると、
type=password
が解除される - バリデーションは、API Key欄とAPI Secret欄の必須チェックのみ
- バリデーションのチェックが全部OKにならないと、Loginボタンは
disable
- 必須チェックを満たしていない欄には、
<mat-error>
によるエラーメッセージが表示される
src/app/private/private.component.html
:
<mat-card class="login-card"> <mat-card-header> <mat-card-title class="login-title">bitFlyer API</mat-card-title> </mat-card-header> <mat-card-content> <form (ngSubmit)="onSubmit()" class="login-form" #loginForm="ngForm"> <mat-form-field> <input matInput placeholder="API Key" id="key" [(ngModel)]="keySet.key" name="key" #key="ngModel" required> <mat-error *ngIf="key.errors?.required">You must enter a value</mat-error> </mat-form-field> <mat-form-field> <input [type]="hide ? 'password' : 'text'" matInput placeholder="API Secret" id="secret" [(ngModel)]="keySet.secret" name="secret" #secret="ngModel" required> <mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 'visibility_off'}}</mat-icon> <mat-error *ngIf="secret.errors?.required">You must enter a value</mat-error> </mat-form-field> <button type="submit" mat-raised-button color="primary" [disabled]="loginForm.invalid">Login</button> </form> </mat-card-content> </mat-card>
src/app/private/private.component.ts
:
import { Component, OnInit } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; export class PrivateAPIKeySet { constructor(public key: string, public secret: string) {} } @Component({ selector: 'app-private', templateUrl: './private.component.html', styleUrls: ['./private.component.scss'] }) export class PrivateComponent implements OnInit { keySet = new PrivateAPIKeySet('', ''); hide = true; constructor() {} ngOnInit() {} onSubmit() { console.log(this.keySet); } }
src/app/private/private.component.scss
:
.login-card { max-width: 400px; } .login-form { display: flex; flex-direction: column; } .login-title { font-weight: bold; font-size: 22px; color: #3f51b5; }