Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
AngularJS TIPS

AngularJS TIPS

入力フォームに検証機能を実装するには?(form/input)

2015年6月22日

標準的な<input>要素を拡張して入力フォームに検証機能を付ける方法を説明する。

  • このエントリーをはてなブックマークに追加

 AngularJSでは、標準的な<input>要素を拡張しており、検証機能付きの入力フォームをコーディングレスで実装できます。さっそくですが、具体的な例を示します。

HTML
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8" />
<title>AngularJS TIPS</title>
<body ng-controller="MyController">
<!--1フォームを用意-->
<form name="myForm" ng-submit="onsubmit()" novalidate>
  <div>
    <label for="name">名前:</label><br />
    <!--2検証ルールを指定-->
    <input id="name" name="name" type="text" ng-model="user.name"
      required ng-minlength="2" ng-maxlength="10" />
    <!--3検証エラーメッセージを表示-->
    <span ng-show="myForm.name.$error.required">
      名前は必須です。</span>
    <span ng-show="myForm.name.$error.minlength">
      名前は2文字以上で入力してください。</span>
    <span ng-show="myForm.name.$error.maxlength">
      名前は10文字以内で入力してください。</span>
  </div>
  <div>
    <label for="age">年齢:</label><br />
    <input id="age" name="age" type="number" ng-model="user.age"
      required min="20" max="60" />
    <span ng-show="myForm.age.$error.required">
      年齢は必須です。</span>
    <span ng-show="myForm.age.$error.min">
      年齢は20以上で入力してください。</span>
    <span ng-show="myForm.age.$error.max">
      年齢は60以下で入力してください。</span>
  </div>
  <div>
    <label for="mail">メールアドレス:</label><br />
    <input id="mail" name="mail" type="email" ng-model="user.mail"
      required />
    <span ng-show="myForm.mail.$error.required">
      メールアドレスは必須です。</span>
    <span ng-show="myForm.mail.$error.email">
      メールアドレスは正しい形式で入力してください。</span>
  </div>
  <div>
    <label for="entry">入会希望日:</label><br />
    <input id="entry" name="entry" type="date" ng-model="user.entry"
      required />
    <span ng-show="myForm.entry.$error.required">
      入会希望日は必須です。</span>
    <span ng-show="myForm.entry.$error.date">
      入会希望日は正しい形式で入力してください。</span>
  </div>
    <label for="memo">備考:</label><br />
    <textarea id="memo" name="memo" rows="5" cols="30"
      ng-model="user.memo" ng-maxlength="10"></textarea>
    <span ng-show="myForm.memo.$error.maxlength">
      備考は10文字以内で入力してください。</span>
  </div>
  <div>
    <!--4フォーム全体の検証が成功していればクリック可能に-->
    <input type="submit" value="申込"
      ng-disabled="myForm.$invalid" />
  </div>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<script>
angular.module('myApp', [])
  .controller('MyController', ['$scope', function($scope) {
    $scope.onsubmit = function() {
      console.log('名前:' + $scope.user.name);
      console.log('年齢:' + $scope.user.age);
      console.log('メールアドレス:' + $scope.user.mail);
      console.log('入会希望日:' + $scope.user.entry);
      console.log('備考:' + $scope.user.memo);
    };
  }]);
</script>
</body>
</html>
検証機能付きの入力フォームを実装したコード(form.html)
入力値が不正の場合はエラーメッセージを表示

 ポイントとなるのは、以下の点です。

1入力フォームを準備する

 標準的なHTMLと同じく、フォームは<form>要素で定義します。ただし、以下の点に注意してください。

  • あとから検証結果を参照するためにname属性(=フォームの名前)は必須
  • HTML5の検証機能とバッティングしないよう、novalidate属性(=HTML5検証の無効化)は必須
  • サブミット時の挙動はng-submit属性で定義

 ng-submit属性は、<form>要素でaction属性(=ポスト先)が指定されない場合、サーバーへのデータ送信をキャンセルします。AngularJSアプリの場合、基本的にはイベントリスナーの中で$http$resourceサービスによってデータを送信しているはずなので*1、いちいちキャンセルしなくてよいのは便利です。

  • *1 サンプルでは、単にログを出力するにとどめています。

2検証ルールを指定する

 <input>要素では、それぞれtype属性に応じて、以下のような検証属性が用意されています。

type属性 属性 概要
共通 required 必須であるか
ng-required 必須であるか(Angular式で指定)
number/date/time/datetime-local/month/week min 最小値
max 最大値
text/number/email/url/<textarea> ng-minlength 最小文字数
ng-maxlength 最大文字数
ng-pattern 正規表現パターンに合致するか
入力型(type)ごとの検証属性

 検証機能を利用する場合には、あとでエラー情報を参照するために、name属性は必須です。

 minmax属性に渡す日付/時刻値は、ISO-8601で規定された形式でなければなりません。date(日付)であれば2015-08-05ですし、time(時刻)であれば19:45:31、日付時刻(datetime-local)であれば2015-08-05T19:45:31です。

3検証エラーメッセージを表示する

 検証エラー情報はフォーム名.要素名.$error.検証名で参照できます。例えばmyForm.name.$error.requiredで「myFormフォームのname欄(名前)が空か(=必須検証がエラーであるか)」という意味になります。

 利用できる検証名は、以下の通りです。

検証名 概要
required 必須検証
max 最大値検証
min 最小値検証
maxlength 文字列の最大長検証
minlength 文字列の最小長検証
pattern 正規表現検証
number 数値検証
url URLのフォーマット検証
email メールアドレスのフォーマット検証
date 日付のフォーマット検証
datetimelocal 日付/時刻のフォーマット検証
time 時刻のフォーマット検証
week 週のフォーマット検証
month 月のフォーマット検証
利用可能な検証名

 ここでは、$error変数をng-show属性に渡すことで、検証エラーがあった場合にだけ対応するメッセージを表示します。AngularJS 1.3以降では、エラーメッセージをより効率的に管理するためのng-messages/ng-message属性もありますが、こちらについては別稿「TIPS:式の真偽に応じて表示を切り替えるには?」で解説の予定です。

4フォーム全体の検証の成否を判定する

 個々の検証項目ではなく、フォーム全体で何らかの検証エラーが発生しているかを判定するには、フォーム名.$invalidを参照します。ここでは、この値をサブミットボタンのng-disabled属性にセットすることで、検証エラーがある場合(=$invalidプロパティがtrueである場合)にサブミットボタンを無効にしています。これによって、検証を全て通過した場合にだけ、サブミットできるボタンを作成できます。

 ちなみに、その他にも、フォームの状態を監視するために、以下のようなプロパティが用意されています。

構文 概要
フォーム名.$valid フォーム配下の入力値が全て正しいか
フォーム名.$pristine フォームは変更されていないか
フォーム名.$dirty フォームが変更されているか
フォーム名.要素名.$valid 入力項目が正しい値であるか
フォーム名.要素名.$invalid 入力項目が不正な値であるか
フォームの状態を表すプロパティ
処理対象:入力検証 カテゴリ:基本
処理対象:ディレクティブ(Directive) カテゴリ:基本
API:input|ngSubmit(ng-submit)|ngShow(ng-show) カテゴリ:ng(コアモジュール) > directive(ディレクティブ)

※以下では、本稿の前後を合わせて5回分(第12回~第16回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

AngularJS TIPS
12. 入力された区切り文字を配列に変換するには?(ng-list)

テキストボックスへの入力値を特定の区切り文字で分割して文字列の配列に変換するために、ng-list属性を使用する方法を解説する。

AngularJS TIPS
13. URL/メールアドレスからハイパーリンクを生成するには?(linky)

URL/メールアドレスの文字列データをアンカータグによるリンクに整形できるlinkyフィルターの基本的な使い方を説明する。

AngularJS TIPS
14. 【現在、表示中】≫ 入力フォームに検証機能を実装するには?(form/input)

標準的な<input>要素を拡張して入力フォームに検証機能を付ける方法を説明する。

AngularJS TIPS
15. 式の真偽に応じて表示を切り替えるには?(ng-messages/ng-message)

条件式の値に応じてメッセージの表示/非表示を切り替えるために(例えばエラー時にメッセージ表示するなど)、ng-messages/ng-message属性を使用する方法を解説する。

AngularJS TIPS
16. 別ファイルやJavaScriptでメッセージを管理するには?(ng-message-include/ng-message-exp)

ng-messages属性で使用するメッセージを、ページ内でテンプレート化したり、外部ファイル化したりして効率的に管理する方法を説明する。

サイトからのお知らせ

Twitterでつぶやこう!