読者です 読者をやめる 読者になる 読者になる

/var/log/laughingman7743.log

I thought what I'd do was, I'd pretend I was one of those deaf-mutes or should I?

いまさらながらKnockoutJSに入門してみた - フォームバリデーション

RestAPIとJavaScriptによるシングルページのアプリではなく、基本的にサーバサイドのテンプレートエンジンをガッツリ利用する形で、 フォームのリアルタイムバリデーションを低コストで実現したかったので、いまさらながらKnockoutJSに入門してみました。
(Vue.jsも合わせてさわってみましたが、複数項目のバリデーションができなさそうだったのでKnockoutJSを使うことに)

フォームバリデーション以外はおそらく書かないのであしからず。。。

Knockout Validation*1を利用します。
基本的なバリデーションについてはドキュメントを見れば簡単にできるので割愛。実践的な例を。

Bootstrapでエラー表示

Bootstrapの場合、input自体にクラスを追加してもエラー表示とならないので少し工夫が必要です。 といっても簡単にできて、バリデーション初期化時の設定でerrorElementClassにhas-errorを設定し、 inputを囲んでいる親divにvalidateElementをバインディングしてやるだけです。

テキストボックスのリアルタイムバリデーション

KnockoutJS 3.2.0からはtextinputバインディングを使うことで、入力されたタイニングでバリデーションをかけることができるようになっています。*2

カスタムバリデータ

ko.validation.rulesを拡張することで、バリデーションの定義を追加することができます。 ko.validation.registerExtendersを呼び出すのを忘れずに。 以下はメールアドレスのローカルパートの長さに制限をかけるような例です。

条件付きバリデーション

onlyIfプロパティで制御できます。 以下はいくつかの項目があり、その1つでも入力されている場合にその他全て入力必須とするような例です。(関連する項目があるので、onlyIfで指定したメソッド内で各項目のvalueHasMutatedを呼び出して、変更があった項目以外のバリデーションも走らせる必要があります。もう少しうまい方法があるかも。。。 computedを使う形でうまくできる感じです。初期表示で関連する項目に入力がなく、関連項目のバリデーションが走らない場合は、ビューモデル生成後に各項目のnotifySubscribersを呼び出し、一度バリデーションを走らせれば*3うまくできます)

関連項目バリデーション

カスタムバリデーション定義をうまく利用することでできます。 以下は商品の価格帯を入力するような場合で、一方の値が一方の値より大きな値を入力しないとエラーとするような例です。 バリデーターに渡される第1引数は使わず、バリデーション定義時に指定したparamsからko.validation.utils.getValueで値を取得して比較するような形です。

コンテキストを分ける

フォームがタブで分かれていてそれぞれのタブでビューモデルを管理したい場合は、withバインディングでコンテキストを分けることができます。 withバインディングはコメントを拡張する形で書けるので、コンテキストを分けるためにタグを用意する必要はなかったりします。(ifバインディングやforバインディングも同様にコメントを拡張する形で書けます。デザインを崩さずに済むので便利です)

エラー件数

ko.validatedObservableのerrosメソッドのlengthプロパティからエラー件数を取得できます。 以下は各タブごとのエラー件数と、全てのタブのエラー件数を表示するような例です。 コンテキストを分けている場合は、各タブのエラー件数をcomputedする形で全てのタブのエラー件数を取得できます。エラー件数で送信ボタンを制御することも簡単にできます。

KnockoutJSはシンプルで学習コストも低く、手軽に双方向バインディングが実現できて素敵ですね。 jQueryでDOMを直接いじることに制限はないので、いざとなったらDOMを直接いじる逃げ道も。。。

ReactやAngularJSが何かと話題ですが、あまり大きな規模の開発でなければ、KnockoutJSやVue.jsのような 手軽に使えるMVVMフレームワークが良い感じです。食わず嫌いは良くないですね。

Enjoy!