AngularJSでフォームまわりで最初はバリデーションメッセージを表示せず、フォーカスが外れたタイミングで表示する術

こんにちは。昼に煮込みうどんをたべました。きたけーです。

細かいテクニックですが、AngularJSでフォームでページを表示した最初はバリデーションメッセージを表示せず、フォーカスが外れたタイミングで表示する術を見つけたのでメモ。

なんでやるの?

  • ページを表示したタイミングで「入力してください」みたいなメッセージが表示されていたら萎える
  • 文字入力するたびにメッセージが表示されるとしつこい(場合もある)

AngularJSで以下のように書くと、↑のようなかんじになります。

<form name="signupForm" novalidate ng-submit="signupForm()">
  <label>Your name</label>
  <input type="text" placeholder="Name" name="name" ng-model="signup.name" ng-minlength=3 ng-maxlength=20 ng-pattern="/^[a-zA-Z]*$/" required />

  <div class="error" ng-messages="signupForm.name.$error">
    <div ng-message="required">入力してください</div>
    <div ng-message="minlength">3文字以上入力してください</div>
    <div ng-message="maxlength">20文字以下で入力してください</div>
    <div ng-message="pattern">半角英字のみで入力してください</div>
  </div>
  <button type="submit">Submit</button>
</form>

最初はバリデーションメッセージを表示しない

フォームの内容が変更されたかどうかはsignupForm.$dirtyでハンドリングできるので、以下のようにng-showで表示を切り替えます。これで最初にページを表示したタイミングでバリデーションメッセージを非表示にできます。

<div class="error" ng-messages="signupForm.name.$error" ng-show="signupForm.$dirty">

フォーカスが外れたタイミングで表示する

ng-model-optionsでモデルの値を変更するタイミングを指定できるので、ここを「フォーカスが外れたとき」にすることで、モデルの値が変わる(=バリデーションが走る、バリデーションメッセージが表示される)タイミングを制御することができます。

<input type="text" placeholder="Name" name="name" ng-model="signup.name" ng-model-options="{updateOn: 'blur'}" ng-minlength=3 ng-maxlength=20 ng-pattern="/^[a-zA-Z]*$/" required />