hifiveとjQuery UIを組み合わせる【バリデーション】
hifiveは業務システム開発に特化しているのでjQuery UIやBootstrapと組み合わせて使われることが多くなっています。そこで今回はよく使われるライブラリについて、その組み合わせ方を紹介します。
今回はバリデーションです。
デモコードについて
実際に動作するデモはJSFiddleにアップロードしてあります。入力して送信ボタンを押すとバリデーションが実行されます。
HTMLについて
HTMLは次のようになります。通常のHTMLと変わりません。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<form method="get" action="#" id="form1"> | |
<fieldset> | |
<legend>アンケート</legend> | |
<div> | |
<div>好きな食べ物を選択して下さい</div> | |
<input type="checkbox" value="1" name="food">和食 <input | |
type="checkbox" value="2" name="food">中華 <input | |
type="checkbox" value="3" name="food">イタリアン <input | |
type="checkbox" value="4" name="food">フレンチ <span | |
class="errorMsg"></span> | |
</div> | |
<br> | |
<div> | |
<div>タバコを吸っていますか?</div> | |
<div> | |
<input type="radio" value="yes" name="conf_tobacco">はい <input | |
type="radio" value="no" name="conf_tobacco">いいえ <span | |
class="errorMsg"></span> | |
</div> | |
<br> | |
<div>1日の喫煙本数</div> | |
<div> | |
<input type="text" name="count">本 <span class="errorMsg"></span> | |
</div> | |
</div> | |
</fieldset> | |
<p> | |
<fieldset> | |
<legend>ユーザ情報登録</legend> | |
<div> | |
<div>URL(任意)</div> | |
<input type="text" name="url"> <span class="errorMsg"></span> | |
</div> | |
<p> | |
<div> | |
<div>ユーザID ("hifive"以外を入力すると「入力されたユーザ名は既に使用されています」がエラーメッセージに表示されます)</div> | |
<input type="text" name="userid"> <span class="errorMsg"></span> | |
</div> | |
<div> | |
<div>パスワードを入力(8~12文字)</div> | |
<input type="password" name="pass"> <span class="errorMsg"></span> | |
</div> | |
<div> | |
<div>パスワードを再入力</div> | |
<input type="password" name="conf_pass"> <span | |
class="errorMsg"></span> | |
</div> | |
<br> | |
</fieldset> | |
<br /> | |
<input type="submit" value="送信" /> | |
</p> | |
</form> |
CSSについて
CSSはエラー時の色をつけるクラスなどを追加しています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@charset "utf-8"; | |
#form1 { | |
border: 1px solid black; | |
padding: 15px; | |
} | |
.errorMsg { | |
color: red; | |
} | |
.strong { | |
font-weight: bold; | |
} | |
.rules { | |
border-collapse: collapse; | |
} | |
.rules td { | |
border: 1px solid black; | |
} |
JavaScriptについて
JavaScriptは長いので、幾つかに分けて紹介します。まず、hifiveのコントローラ化が完了した際の__readyイベントにてバリデーションの設定を行います。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
this.$find('#form1').validate({ | |
// Submitイベントが実行された場合に、自動でバリデーションを実行 | |
onsubmit: true, | |
// フォーカスが当たった場合に現在のエラー内容を一旦クリア | |
focusCleanup: true, | |
// バリデーションルール | |
rules: { | |
food: { | |
required: true | |
}, | |
conf_tobacco: { | |
required: true | |
}, | |
count: { | |
required: { | |
depends: '[name="conf_tobacco"][value="male"]:checked' | |
}, | |
number: { | |
depends: '[name="conf_tobacco"][value="male"]:checked' | |
}, | |
min: { | |
param: 1, | |
depends: '[name="conf_tobacco"][value="male"]:checked' | |
}, | |
max: { | |
param: 999, | |
depends: '[name="conf_tobacco"][value="male"]:checked' | |
} | |
}, | |
lastname: { | |
required: true | |
}, | |
firstname: { | |
required: true | |
}, | |
email: { | |
required: true, | |
email: true | |
}, | |
url: { | |
url: true | |
}, | |
userid: { | |
required: true, | |
minlength: 6, | |
remote: '/exists' // useridをパラメータのキーにして、/existsに結果を問い合わせる (サーバは"true"または"false"の文字列を返す必要がある) | |
}, | |
pass: { | |
required: true, | |
rangelength: [8, 12] | |
}, | |
conf_pass: { | |
equalTo: '[name="pass"]' | |
}, | |
policy: { | |
required: true | |
} | |
}, | |
messages: { // エラー時に表示するメッセージ | |
food: { | |
required: '1つ以上選択して下さい。' | |
}, | |
conf_tobacco: { | |
required: '「はい」または「いいえ」のいずれかを選択して下さい' | |
}, | |
count: { | |
required: '「はい」を選択した場合は、喫煙本数を入力して下さい', | |
number: '本数は数字で入力して下さい', | |
min: '{0}以上の値を入力して下さい', | |
max: '{0}以下の値で入力して下さい' | |
}, | |
lastname: { | |
required: '姓を入力して下さい' | |
}, | |
firstname: { | |
required: '名を入力して下さい' | |
}, | |
email: { | |
required: 'メールアドレスを入力して下さい', | |
email: '正しいメールアドレスを入力して下さい' | |
}, | |
url: { | |
url: '正しいURLを入力して下さい' | |
}, | |
userid: { | |
required: 'ユーザIDを入力して下さい。', | |
minlength: '{0}以上で入力して下さい。', | |
remote: '入力されたユーザ名は既に使用されています' | |
}, | |
pass: { | |
required: 'パスワードを入力して下さい', | |
rangelength: '{0}以上{1}文字以下で入力して下さい' | |
}, | |
conf_pass: { | |
equalTo: 'パスワードが一致しません' | |
}, | |
policy: { | |
required: '同意される場合はチェックを入れて下さい' | |
} | |
}, | |
// エラーメッセージの表示先を指定する | |
errorPlacement: function(error, el) { | |
el.parent().children('.errorMsg').append(error); | |
}, | |
// エラーがある要素毎に実行するコールバック | |
showErrors: function(errorMap, errorList) { | |
this.defaultShowErrors(); | |
}, | |
// 入力項目でエラーがあったときに実行されるハンドラ | |
highlight: this.ownWithOrg(this.highLightArea), | |
// エラーが解消されたときに実行されるハンドラ, | |
unhighlight: this.ownWithOrg(this.unHighLightArea), | |
// validateのチェックが通り、submitが行われるときに実行するハンドラ | |
submitHandler: this.ownWithOrg(this.submitHandler), | |
// validateでエラーが1つでもあると実行されるハンドラ | |
invalidHandler: this.ownWithOrg(this.invalidHandler), | |
// 入力項目でエラーが解消されるたびに実行されるハンドラ | |
success: this.ownWithOrg(this.successHandler) | |
}); |
この際、入力チェックを行う際などのイベントハンドラも設定もします。this.ownWithOrgを使うことでhifiveのコントローラ自身を渡せるようになります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// エラーがある要素毎に実行するコールバック | |
showErrors: function(errorMap, errorList) { | |
this.defaultShowErrors(); | |
}, | |
// 入力項目でエラーがあったときに実行されるハンドラ | |
highlight: this.ownWithOrg(this.highLightArea), | |
// エラーが解消されたときに実行されるハンドラ, | |
unhighlight: this.ownWithOrg(this.unHighLightArea), | |
// validateのチェックが通り、submitが行われるときに実行するハンドラ | |
submitHandler: this.ownWithOrg(this.submitHandler), | |
// validateでエラーが1つでもあると実行されるハンドラ | |
invalidHandler: this.ownWithOrg(this.invalidHandler), | |
// 入力項目でエラーが解消されるたびに実行されるハンドラ | |
success: this.ownWithOrg(this.successHandler) |
後は各イベントハンドラの実装になります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 入力項目でエラーがあったときに実行されるハンドラ | |
highLightArea: function(orgThis, el, error, errorClass) { | |
$(el).css('background-color', 'red'); | |
}, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// エラーが解消されたときに実行されるハンドラ, | |
unHighLightArea: function(orgThis, el, error, errorClass) { | |
var $el = $(el); | |
$el.css('background-color', ''); | |
// 操作した要素が「1日の喫煙本数」テキストボックスでかつ、「たばこを吸っていますか」チェックボックスが「いいえ」の場合は、 | |
// 「1日の喫煙本数」テキストボックスのハイライトを除去する | |
if ($el.is('[name="conf_tobacco"]') && this.$find('[name="conf_tobacco"]:checked').val() === 'female') { | |
this.$find('[name="count"]').css('background-color', ''); | |
} | |
}, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// validateのチェックが通り、submitが行われるときに実行するハンドラ | |
submitHandler: function(orgThis, form, ev) { | |
alert('FORMの内容をサーバに送信します。'); | |
form.submit(); | |
}, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// validateでエラーが1つでもあると実行されるハンドラ | |
invalidHandler: function(orgThis, ev, validator) { | |
alert('入力内容に誤りがあります。'); | |
}, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 入力項目でエラーが解消されるたびに実行されるハンドラ | |
successHandler: function(orgThis, errMsgElement, inputElement) { | |
if (window.console) { | |
console.log('入力OK: '+ inputElement.name); | |
} | |
}, |
最後にチェックボックス、ラジオボタンのバリデーションについて別途実装します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//「好きな食べ物を選択して下さい」のバリデーション | |
'[name="food"] click': function(context, $ct) { | |
// input[name="food"]の要素に対してバリデーションを実行する | |
$ct.valid(); | |
}, | |
//「1日の喫煙本数」テキストボックスのバリデーション | |
'[name="count"] focusout': function(context, $ct) { | |
// input[name="count"]の要素に対してバリデーションを実行する | |
$ct.valid(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(function() { | |
h5.core.controller('body', { | |
__name: 'sample.plugin.validationSampleController', | |
__ready:function() { | |
// バリデーターにルールやメッセージ等を設定 | |
this.$find('#form1').validate({ | |
// Submitイベントが実行された場合に、自動でバリデーションを実行 | |
onsubmit: true, | |
// フォーカスが当たった場合に現在のエラー内容を一旦クリア | |
focusCleanup: true, | |
// バリデーションルール | |
rules: { | |
food: { | |
required: true | |
}, | |
conf_tobacco: { | |
required: true | |
}, | |
count: { | |
required: { | |
depends: '[name="conf_tobacco"][value="yes"]:checked' | |
}, | |
number: { | |
depends: '[name="conf_tobacco"][value="yes"]:checked' | |
}, | |
min: { | |
param: 1, | |
depends: '[name="conf_tobacco"][value="yes"]:checked' | |
}, | |
max: { | |
param: 999, | |
depends: '[name="conf_tobacco"][value="yes"]:checked' | |
} | |
}, | |
url: { | |
url: true | |
}, | |
// useridをパラメータのキーにして、/existsに結果を問い合わせる | |
// サーバは"true"または"false"の文字列を返す必要がある | |
userid: { | |
required: true, | |
minlength: 6, | |
remote: '/exists' | |
}, | |
pass: { | |
required: true, | |
rangelength: [8, 12] | |
}, | |
conf_pass: { | |
equalTo: '[name="pass"]' | |
}, | |
policy: { | |
required: true | |
} | |
}, | |
messages: { // エラー時に表示するメッセージ | |
food: { | |
required: '1つ以上選択して下さい。' | |
}, | |
conf_tobacco: { | |
required: 'はい、またはいいえを選択して下さい' | |
}, | |
count: { | |
required: '「はい」を選択した場合は、喫煙本数を入力して下さい', | |
number: '本数は数字で入力して下さい', | |
min: '{0}以上の値を入力して下さい', | |
max: '{0}以下の値で入力して下さい' | |
}, | |
url: { | |
url: '正しいURLを入力して下さい' | |
}, | |
userid: { | |
required: 'ユーザIDを入力して下さい。', | |
minlength: '{0}以上で入力して下さい。', | |
remote: '入力されたユーザ名は既に使用されています' | |
}, | |
pass: { | |
required: 'パスワードを入力して下さい', | |
rangelength: '{0}以上{1}文字以下で入力して下さい' | |
}, | |
conf_pass: { | |
equalTo: 'パスワードが一致しません' | |
} | |
}, | |
// エラーメッセージの表示先を指定する | |
errorPlacement: function(error, el) { | |
el.parent().children('.errorMsg').append(error); | |
}, | |
// エラーがある要素毎に実行するコールバック | |
showErrors: function(errorMap, errorList) { | |
this.defaultShowErrors(); | |
}, | |
// 入力項目でエラーがあったときに実行されるハンドラ | |
highlight: this.ownWithOrg(this.highLightArea), | |
// エラーが解消されたときに実行されるハンドラ, | |
unhighlight: this.ownWithOrg(this.unHighLightArea), | |
// validateのチェックが通り、submitが行われるときに実行するハンドラ | |
submitHandler: this.ownWithOrg(this.submitHandler), | |
// validateでエラーが1つでもあると実行されるハンドラ | |
invalidHandler: this.ownWithOrg(this.invalidHandler), | |
// 入力項目でエラーが解消されるたびに実行されるハンドラ | |
success: this.ownWithOrg(this.successHandler) | |
}); | |
}, | |
highLightArea: function(orgThis, el, error, errorClass) { | |
$(el).css('background-color', 'red'); | |
}, | |
unHighLightArea: function(orgThis, el, error, errorClass) { | |
var $el = $(el); | |
$el.css('background-color', ''); | |
// 操作した要素が「1日の喫煙本数」テキストボックスでかつ、「たばこを吸っていますか」チェックボックスが「いいえ」の場合は、 | |
// 「1日の喫煙本数」テキストボックスのハイライトを除去する | |
if ($el.is('[name="conf_tobacco"]') && this.$find('[name="conf_tobacco"]:checked').val() === 'no') { | |
this.$find('[name="count"]').css('background-color', ''); | |
} | |
}, | |
submitHandler: function(orgThis, form, ev) { | |
alert('FORMの内容をサーバに送信します。'); | |
form.submit(); | |
}, | |
invalidHandler: function(orgThis, ev, validator) { | |
alert('入力内容に誤りがあります。'); | |
}, | |
successHandler: function(orgThis, errMsgElement, inputElement) { | |
if (window.console) { | |
console.log('入力OK: '+ inputElement.name); | |
} | |
}, | |
//「好きな食べ物を選択して下さい」のバリデーション | |
'[name="food"] click': function(context, $ct) { | |
// input[name="food"]の要素に対してバリデーションを実行する | |
$ct.valid(); | |
}, | |
//「1日の喫煙本数」テキストボックスのバリデーション | |
'[name="count"] focusout': function(context, $ct) { | |
// input[name="count"]の要素に対してバリデーションを実行する | |
$ct.valid(); | |
} | |
}); | |
}); |
hifiveでもvalidation機能を提供していますが、使い慣れた方を採用するケースもあるでしょう。そうした時にはコールバックの管理などはhifiveで行うことで、よりメンテナンスしやすいバリデーション実装ができるようになります。
実際に動作するデモはJSFiddleにアップロードしてあります。お試しください。
コメントは受け付けていません。