Angularにより拡張されている標準的な<form>/<input>要素を使って、検証機能付きの入力フォームを実装する方法を説明する。
※現在では、Web標準技術を利用したアプリ開発が広く普及し、そのためのフレームワークも多数存在しています。その中でも主流のフレームワークの1つである「Angular」を活用し、そのための知識を備えることには大きな意味があります。本連載は、Angularユーザーに向けて、その使いこなしTIPSを紹介するものです。なお、本連載は「Build Insider」で公開していた連載「Angular Tips」を同サイトおよび筆者の了解を得たうえで、本フォーラムに移行したものです。記事はBuild Insiderで公開した状態のまま移行しているため、用語統一などの基準が@ITの通常の記事とは異なる場合があります。
Angular 5以降。v5時点で執筆しました。
Angularでは、標準的な<form>/<input>要素を拡張しており、検証機能付きの入力フォームをコーディングレスで実装できます。さっそくですが、具体的な例を示します。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule} from '@angular/forms';
import { AppComponent } from './app.component';
// [1]FormsModuleモジュールを有効化
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule, FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<!-- [2]入力フォームを準備-->
<form #myForm="ngForm" (ngSubmit)="show()">
<div>
<label for="name">名前:</label><br />
<!-- [3]検証用の属性を付与したinput要素 -->
<input id="name" name="name" type="text" [(ngModel)]="user.name"
required minlength="2" maxlength="10" #name="ngModel" />
<!-- [4]検証結果を参照 -->
<span [hidden]="!name.errors?.required">
名前は必須です。</span>
<span [hidden]="!name.errors?.minlength">
名前は2文字以上で入力してください。</span>
<span [hidden]="!name.errors?.maxlength">
名前は10文字以内で入力してください。</span>
</div>
<div>
<label for="age">年齢:</label><br />
<input id="age" name="age" type="number" [(ngModel)]="user.age"
required #age="ngModel" />
<span [hidden]="!age.errors?.required">
年齢は必須です。</span>
</div>
<div>
<label for="mail">メールアドレス:</label><br />
<input id="mail" name="mail" type="email" [(ngModel)]="user.mail"
required email #mail="ngModel" />
<span [hidden]="!mail.errors?.required">
メールアドレスは必須です。</span>
<span [hidden]="!mail.errors?.email">
メールアドレスは正しい形式で入力してください。</span>
</div>
<div>
<label for="entry">入会希望日:</label><br />
<input id="entry" name="entry" type="date" [(ngModel)]="user.entry"
required date #entry="ngModel" />
<span [hidden]="!entry.errors?.required">
入会希望日は必須です。</span>
</div>
<div>
<label for="memo">備考:</label><br />
<textarea id="memo" name="memo" rows="5" cols="30"
[(ngModel)]="user.memo" maxlength="10" #memo="ngModel">
</textarea>
<span [hidden]="!memo.errors?.maxlength">
備考は10文字以内で入力してください。</span>
</div>
<div>
<!-- [5]エラーが存在する場合はボタンを無効化 -->
<input type="submit" value="申込"
[disabled]="myForm.invalid" />
</div>
</form>
`
})
export class AppComponent {
// フォームのデフォルト値
user = {
name: '',
age: 20,
mail: 'dummy@example.com',
entry: '2018-01-01',
memo: ''
};
// サブミット時に入力値をログ出力
show() {
console.log('名前:' + this.user.name);
console.log('年齢:' + this.user.age);
console.log('メールアドレス:' + this.user.mail);
console.log('入会希望日:' + this.user.entry);
console.log('備考:' + this.user.memo);
}
}
入力値検証の機能を備えたフォームを実装するためのポイントは、以下の通りです。
[1]FormsModuleモジュールを有効化する
Angularのフォーム機能を利用するには、FormsModuleを有効にしておく必要があります。これには、app.module.tsファイル(メインモジュール)で、@NgModuleデコレーターのimportsパラメーターにFormsModuleを追加してください。
[2]<form>要素で利用できる属性
冒頭でも述べたように、Angularでは標準的な<form>要素を拡張し、フォーム制御のための機能を付与しています。入力値検証を実装するには、最低限、以下の属性を追加します。
No. | 属性 | 概要 |
---|---|---|
a | #myForm="ngForm" | ngFormディレクティブを変数に登録 |
b | (ngSubmit)="show()" | サブミット時の処理を登録 |
<form>要素で利用する属性 |
aは、テンプレート参照変数です。ngFormディレクティブはAngularアプリでフォームを制御するためのディレクティブで、(例えば)入力値と、その検証結果を追跡するのもngFormディレクティブの役割です。ここでは、<form>要素に内部的に適用されたngFormディレクティブを、テンプレート参照変数myFormに代入して、後からフォームの情報――入力要素の状態(検証結果など)にアクセスできるようにしています。
ngSubmitは、ngFormディレクティブで提供しているsubmitイベントです。bはEvent Bindingの一種で、サブミット時にshowメソッドを呼び出しなさい、という意味です。本稿では、showメソッドで入力値をログ出力しているだけですが、一般的には@angular/httpモジュールなどを利用してサーバーにデータ送信するようなコードを記述することになるはずです。
[3]<input>要素で利用できる属性
<form>要素と同じく、<input>/<textarea>要素もまた、Angularによって機能拡張されており、入力値検証や入力要素そのものの状態管理などに関する機能が付与されています。利用できる主な属性を、以下にまとめておきます。
No. | 属性 | 概要 |
---|---|---|
a | name | 入力要素の名前 |
b | [(ngModel)] | 入力要素をバインドすべきプロパティ |
c | #xxxx="ngModel" | ngModelディレクティブを変数に登録 |
d | required | 必須検証(trueで有効) |
e | maxlength | 文字列長検証(値は最大長) |
f | minlength | 文字列長検証(値は最小長) |
g | pattern | 妥当な文字列パターン(値は許可する正規表現) |
h | メールアドレス検証(trueで有効) | |
入力要素で利用する属性 |
ngModel(b)は、フォームからの入力値とコンポーネントのプロパティとをひも付けるためのディレクティブです。詳しくは、別稿「TIPS:フォームの入力値をコンポーネントと同期するには?」も併せて参照してください。ngModelディレクティブを利用する場合には、Angularが入力要素を識別できるよう、name属性(a)は必須です。
cは、<form>要素のときと同じく、テンプレート参照変数です。ngModelディレクティブを代入しておくことで、後から検証結果にアクセスできるようになります。
d〜hは具体的な検証ルールの指定です。required/email属性については値としてtrueを指定するだけで有効になりますが、それ以外の属性は検証内容に応じてパラメーターを渡してください。
[4]検証結果を参照する
検証結果は「入力要素名.errors?.検証型」という式で検証できます。検証エラーが存在していればtrue、さもなければfalseを返します*1。検証型には、検証ルールに応じてrequired、maxlength、minlength、pattern、emailなどを指定できます。
*1 「?」は存在演算子です。詳細は別稿「TIPS:ビューの中で「安全に」プロパティ/メソッドにアクセスするには?」も併せて参照してください。
[4]であれば、「[hidden]="!name.errors?.required"」としているので、検証エラーがなければ(=検証に成功していれば)hidden属性をtrueにし、エラーメッセージを非表示します。
[5]フォーム全体の妥当性を確認する
フォーム全体の入力値にエラーが存在するかどうかを確認するには、「フォーム名.invalid」とします。この例であれば、サブミットボタンのdisabledプロパティに「myForm.invalid」という式を渡すことで、入力値に不正(invalid)な値がある場合にはボタンを無効化しなさい、という意味になります。これで、全ての入力が正しい場合にだけ、フォームを送信できるようになるわけです。
ちなみに、フォーム全体で入力値が正しいかをチェックするには、「フォーム名.valid」にアクセスします。同じように、入力要素単位にエラーの有無をチェックするには、「入力要素名.valid」「入力要素名.invalid」とします。
処理対象:ディレクティブ(Directive) カテゴリ:基本
API:NgForm(ngForm)|NgModel(ngModel) カテゴリ:@angular > forms > DIRECTIVE(ディレクティブ)
API:FormsModule カテゴリ:@angular > forms > CLASS(クラス)
API:@NgModuleデコレーター カテゴリ:ADVANCED > Angular Modules
Copyright© Digital Advantage Corp. All Rights Reserved.