Angularで「フォーム」の状態を監視するには?(ngForm/ngModel):Angular TIPS
Angularにより拡張されている標準的な<form>/<input>要素を使って、入力の有無を判定したり、サブミット済みかを判定したりと、その状態を監視する方法を説明する。
※現在では、Web標準技術を利用したアプリ開発が広く普及し、そのためのフレームワークも多数存在しています。その中でも主流のフレームワークの1つである「Angular」を活用し、そのための知識を備えることには大きな意味があります。本連載は、Angularユーザーに向けて、その使いこなしTIPSを紹介するものです。なお、本連載は「Build Insider」で公開していた連載「Angular Tips」を同サイトおよび筆者の了解を得たうえで、本フォーラムに移行したものです。記事はBuild Insiderで公開した状態のまま移行しているため、用語統一などの基準が@ITの通常の記事とは異なる場合があります。
【対応バージョン】
Angular 5以降。v5時点で執筆しました。
別稿「TIPS:入力フォームに検証機能を実装するには?」でも触れたように、AngularではngForm/ngModelディレクティブを利用することで、入力値の妥当性を検証し、不正な値に対してはエラーメッセージを表示することができます。
もっとも、ngForm/ngModelの機能はそれだけではありません。入力の有無を判定したり、サブミット済みかどうかを判定したりすることも可能です。本稿では、Angularのフォームで、その状態を監視するための方法についてまとめます。なお、サンプルとしては、前掲の別稿で利用したものからの差分のみを掲載します。
入力済みかどうかを判定する
フォーム、または個々の要素が入力済みであるかどうかを判定するには「名前.dirty」「名前.pristine」のように表します。名前は、フォーム、または入力要素の名前です。
dirtyプロパティはフォーム/要素が変更されている場合にtrueを、pristineプロパティはフォーム/要素が変更されていない場合にtrueを、それぞれ返します(つまり、互いに反対の意味を表すというわけです)。
pristineプロパティを利用することで、(例えば)フォームに何らかの変更があった場合にのみリセットボタンを有効にする、といった動作を実装できます。以下は、その具体的なコードです。
<input type="reset" value="リセット"
[disabled]="myForm.pristine" />
フォームが未変更であればdisabled属性をtrueにし、リセットボタンを無効化しているわけです。
エラーメッセージを最初から表示しない
前掲の別稿のサンプルをそのまま動作した場合、実は、required検証を課した要素でエラーメッセージが最初から表示されてしまいます。
まだ何もしていない状態でエラーメッセージが表示されているのは望ましい状態ではありません。しかし、エラーメッセージ表示のコードに、先ほどのdirtyプロパティによる判定を加えることで、エラーメッセージの初期表示を抑制できます。
<span [hidden]="!(name.errors?.required && name.dirty)">
名前は必須です。</span>
これで、入力要素が変更されており、かつ、required検証がエラーの場合にのみエラーメッセージを表示する、という意味になります。一般的には、エラーメッセージの表示に際しては、dirtyプロパティで変更の有無をチェックすべきです。
[Note]
pristine/dirtyによく似たプロパティとして、touched/untouchedプロパティもあります。こちらは、フォーム/入力要素に一度でもフォーカスしたか、一度もフォーカスしていないかを判定するためのプロパティです。
サブミット済みかどうかを判定する
ngFormのsubmittedプロパティを参照することで、フォームがサブミット済みかどうかを判定できます。submittedプロパティを利用することで、(例えば)サブミット済みの場合は、サブミットボタンを無効化するような仕掛けを実装できます(ごくシンプルな二重送信防止の仕組みです)。
<input type="submit" value="申込"
[disabled]="myForm.invalid || myForm.submitted" />
これで入力に不正な値が混在しているか、一度でもフォームが送信された場合には、disabled属性がtrue(=ボタンが無効化)になります。
フォームの状態に応じてスタイルを変更する
Angularでは、フォームの状態をプロパティとして公開しているばかりではありません。以下のようなスタイルクラスを、フォームの状態に応じて着脱します。
スタイルクラス | 概要 |
---|---|
ng-valid | 値が妥当な場合 |
ng-invalid | 値が不正な場合 |
ng-pristine | 値が変更されていない場合 |
ng-dirty | 値が変更された場合 |
ng-untouched | 要素にフォーカスが当たったことがある場合 |
ng-touched | 要素にフォーカスが当たったことがない場合 |
フォームの状態に関わるスタイルクラス |
これらのスタイルクラスを利用することで、例えば検証エラーが発生した項目だけハイライト表示するような仕組みを簡単に実装できます(ディレクティブ、バインド構文すら不要です)。
@Component({
selector: 'app-root',
template: `
<form #myForm="ngForm" (ngSubmit)="show()">
……中略……
</form>
`,
styles: [`
input.ng-dirty.ng-invalid {
border-color: #f00;
}
`]
})
ng-invalidスタイルだけでなく、ng-dirtyを加えているのは、先ほどと同じ理由です。ng-dirtyがない場合、required検証を課した項目が最初から赤く点灯してしまうので、注意してください。
処理対象:ディレクティブ(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.