knockout-validation の decorateInputElement
knockoutjs + knockout-validation を使うと、フォームのフィールドへの入力値をリアルタイムに検証し、その結果をユーザーにフィードバックする動的フォームをかなり容易に作成できます。
特に、knockout-validation に decorateInputElement: true を与えると、エラーのある input に validationElement クラスを付与できるため、border-colorを変えるなどしてエラー箇所を分かりやすく表示できます。(このオプション、以前は decolateElement と呼ばれていたのですが、名前が変わったそうです)
Bootstrap との組み合わせ
ところがこれを Bootstrap と組み合わせようとすると、ちょっと困ったことになります。
なぜなら Bootstrap ではエラーのあるコントロールの表示を変えるのに input 自身ではなくそれを囲む div.form-group に has-error というクラスを指定しなければならないためです。
knockout-validation では errorElementClass というオプションで、エラーのあるコントロールに付与するクラス名を指定できますが、コントロールを囲む div.form-group にクラスを追加するという機能はないようです。
そこで
コントロールの parentNode をたどり、.form-group にマッチするものに has-error を追加するコードを以下のように書きました。
// 要素の親のうち form-group であり、なおかつエラー要素を含むものに
// config.errorParentClass クラスを指定する
var original_handler = ko.bindingHandlers.validationElement.update;
ko.bindingHandlers.validationElement.update =
function (element, valueAccessor, allBindingsAccessor) {
original_handler(element, valueAccessor, allBindingsAccessor);
var config = ko.validation.utils.getConfigOptions(element);
var group = $(element).parents('.form-group');
group.toggleClass(
'has-error',
group.find("."+config.errorElementClass).length > 0
);
};
1つの form-group に複数のコントロールが含まれる場合、1つでもエラーになるものがあれば has-error となるようにしてあります。
jsfiddle で確かめられます
上記のコードは以下の jsfiddle で確かめられます。