hifiveのバリデーションを使いこなす
ユーザの入力値を検証するのはWebアプリケーションを開発する上で大事な機能です。従来はユーザの入力をサーバサイドで検証し、入力エラーがあれば再度フォームをエラーメッセージとともに表示するのが一般的でした。しかしこの場合、レンダリングにかかる時間であったり、入力を再現するのが面倒(特にファイル送信など)でした。
そこで最近ではJavaScriptを使った入力チェック(バリデーション)が使われるようになっています。もちろんサーバサイドでの入力チェックはこれまで通り必要ですが、まずJavaScript側でチェックをすることで、ユーザストレスを軽減したUXが提供できるようになります。
そこで今回はhifiveの提供する入力値検証ライブラリ、FormControllerの使い方を紹介します。
ベースとなるコントローラ
まず元になるコントローラのコードを紹介します。 .confirmをクリックすると入力値の検証を行うこととします。
(function($) { | |
var reportController = { | |
__name: 'ReportController', | |
__ready: function() { | |
}, | |
'.confirm click': function(context, $el) { | |
// 入力値の検証 | |
}, | |
}; | |
h5.core.expose(reportController); | |
})(jQuery); | |
$(function() { | |
h5.core.controller(document.body, ReportController); | |
}); |
ベースとなるHTMLについて
さらにベースとなるHTML(body内)は次のようになります。UIライブラリとしてBootstrapを読み込んでいます。
<body> | |
<div class="edit container "> | |
<form class="form-horizontal"> | |
<div class="report-content"> | |
<div class="msg alert alert-danger"></div> | |
<div class="worklog"> | |
<div class="common-items row"> | |
<div class="col-sm-4"> | |
<div class="form-group"> | |
<label class="col-sm-3 control-label" for="reportDate">日付</label> | |
<div class="col-sm-9"><input id="reportDate" name="reportDate" type="date" class="form-control"></div> | |
</div> | |
</div> | |
<div class="col-sm-8"> | |
<div class="form-group"> | |
<label class="col-sm-3 control-label" for="startTime">勤務時間</label> | |
<div class="col-sm-9"> | |
<div class="input-group"> | |
<input id="startTime" name="startTime" type="time" class="form-control"> | |
<span class="input-group-addon">~</span> | |
<input id="endTime" name="endTime" type="time" class="form-control"> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="section-wrap"> | |
<div class="section"> | |
<div class="section-header row"> | |
<div class="col-sm-6"> | |
<div class="form-group"> | |
<label class="col-sm-2 control-label" for="category">報告区分</label> | |
<div class="col-sm-10"> | |
<input id="category" name="category" type="text" class="form-control"> | |
</div> | |
</div> | |
</div> | |
<div class="col-sm-6"> | |
<div class="form-group"> | |
<label class="col-sm-3 control-label" for="title">タイトル</label> | |
<div class="col-sm-9"><input id="title" name="title" type="text" class="form-control"></div> | |
</div> | |
</div> | |
</div> | |
<div class="section-content form-group"> | |
<label class="col-sm-1 control-label" for="comment">報告内容</label> | |
<div class="col-sm-11 comment"><textarea id="comment" name="comment" class="form-control"></textarea></div> | |
</div> | |
<div class="section-img form-group"> | |
<label class="col-sm-1 control-label">添付画像</label> | |
<div class="col-sm-11 img-input-wrap"> | |
<input class="form-control" accept="image/*" name="img" type="file"/> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="btn-wrap text-center"> | |
<div class="btn-group"> | |
<button class="cancel">キャンセル</button> | |
<button class="confirm">確認する</button> | |
</div> | |
</div> | |
</form> | |
</div> | |
</body> |
FormControllerを設定する
まず js/index.js
に対してFormControllerを利用する設定を行います。
元:
(function($) { | |
var reportController = { | |
__name: 'ReportController', | |
__ready: function() { | |
: |
修正後:
(function($) { | |
var reportController = { | |
__name: 'ReportController', | |
// バリデーションコントローラの設定 | |
_formController: h5.ui.FormController, | |
__meta: { | |
_formController: { | |
rootElement: 'form' | |
} | |
}, | |
__ready: function() { | |
: |
rootElementというのはバリデーション対象になるフォームのことです。今回はフォームが一つなので form としていますが、複数ある場合は id やクラス名で指定できます。
次に __ready
内で FormControllerの設定を行います。今回は個別の入力項目に対してエラー表示を行うstyleと、フォーム全体のエラーメッセージを表示するcompositionというプラグインを利用します。他にも
- bsBalloon
- message
- balloon
といったプラグインが用意されており、自分で新しいプラグインを作ることもできます。
// バリデーションのプラグイン設定 | |
this._formController.addOutput(['style', 'composition']); |
そして、プラグインに関する設定を行います。
// バリデーションの設定 | |
this._formController.setSetting({ | |
output: { | |
style: { | |
errorClassName: 'has-error', | |
replaceElement: function(element) { | |
return $(element).closest('.form-group'); | |
} | |
}, | |
composition: { | |
container: this.$find('.msg'), | |
wrapper: 'div' | |
}, | |
}, | |
}); |
エラークラス名などはBootstrapのものを使うように指定しています。全体のエラーメッセージは .msg に対して表示するように指定しています。
バリデーションを実行する
バリデーションは確認ボタンを押したタイミングで実行します。
元:
'.confirm click': function(context, $el) { | |
// 初期化 | |
context.event.preventDefault(); | |
: |
修正後:
'.confirm click': function(context, $el) { | |
// 初期化 | |
context.event.preventDefault(); | |
// バリデーション実行 | |
if (!this._formController.validate().isValid) { | |
this.$find(".msg").show(); | |
return false; | |
} else { | |
this.$find(".msg").hide(); | |
} | |
: |
バリデーション自体は this._formController.validate()
にて実行されます。その返却値としてオブジェクトが返ってきますので、その isValid
を使ってバリデーション結果が確認できます。
バリデーションが失敗した場合は、 .msg
を可視化しつつ、処理を完了しています。バリデーションが成功した場合は .msg
を非表示にしています。
index.html の修正
続いて index.html を修正します。こちらでは入力項目に対してバリデーション条件を設定していきます。
元:
<input id="startTime" name="startTime" type="time" class="form-control"> |
修正後:
<input id="startTime" name="startTime" type="time" class="form-control" data-required /> |
このように data-required を追加するだけでstartTimeに対する必須チェックが追加されます。
同じように、
元:
<input id="category" name="category" type="text" class="form-control"> |
修正後:
<input id="category" name="category" type="text" class="form-control" data-required /> |
元:
<div class="col-sm-9"><input id="title" name="title" type="text" class="form-control"></div> |
修正後:
<div class="col-sm-9"><input id="title" name="title" type="text" class="form-control" data-required /></div> |
元:
<div class="col-sm-11 comment"><textarea id="comment" name="comment" class="form-control"></textarea></div> |
修正後:
<div class="col-sm-11 comment"><textarea id="comment" name="comment" class="form-control" data-required data-size="[10,200]" /></textarea></div> |
この報告欄については data-size も使っています。これによって10文字から200文字までの入力という制限を追加しています。
ラベルを日本語化する
ここまでの変更で試すと、エラーメッセージの一部が英語になっているのが分かるかと思います。
categoryは必須項目です
titleは必須項目です
commentは必須項目です
これでは見栄えがよくありませんので、 js/index.js
の this._formController.setSetting
に設定を追加します。
元:
this._formController.setSetting({ | |
output: { | |
style: { | |
errorClassName: 'has-error', | |
replaceElement: function(element) { | |
return $(element).closest('.form-group'); | |
} | |
}, | |
composition: { | |
container: this.$find('.msg'), | |
wrapper: 'div' | |
}, | |
} | |
}); |
修正後:
this._formController.setSetting({ | |
output: { | |
style: { | |
errorClassName: 'has-error', | |
replaceElement: function(element) { | |
return $(element).closest('.form-group'); | |
} | |
}, | |
composition: { | |
container: this.$find('.msg'), | |
wrapper: 'div' | |
}, | |
}, // カンマを忘れずに! | |
property: { | |
title: { | |
displayName: 'タイトル' | |
}, | |
category: { | |
displayName: '報告区分' | |
}, | |
comment: { | |
displayName: '報告内容' | |
} | |
}, | |
}); |
propertyを使って、各入力項目毎に displayName
設定を追加します。ここでラベルを設定してあげることで、入力エラーが
報告区分は必須項目です
タイトルは必須項目です
報告内容は必須項目です
といった具合に日本語化されます。
バリデーションのデモはこちらで試せます。確認ボタンをクリックするとエラーが表示されます。JavaScriptのコード自体はごく短く、設定しか記述していないのを確認してください。
バリデーションを使いこなし、よりユーザビリティの高いWebアプリケーションを目指してください!
コメントは受け付けていません。