本記事の内容について
Knockout.jsを使い始めた際に引っかかる click + checked についての解説です。
というよりも自分が嵌ったので調べた結果です。
まずはそれぞれ実装してみる
取り敢えずそれぞれのバインディングを実装してみます。
checkedについて
checked バインディングは ViewModel のプロパティと チェックボックス () や ラジオボタン () などのチェックできるフォーム部品をリンクします。
ユーザが関連付けられたフォーム部品にチェックを入れると、ViewModel の値が更新されます。 反対に、ViewModel の値を変更することでフォーム部品のチェック状態を変更することができます。
checkedを実装
<label><input type="checkbox" data-bind="checked: isChecked" />テストチェックボックス</label>
var viewModel = {
isChecked: ko.observable(true) // 最初はチェックされた状態
};
この実装に関してはKockoutに関して少し調べた方なら特に問題はないと思います。
clickについて
click バインディングは関連付けられた DOM エレメントがクリックされたときに、 指定した JavaScript 関数を実行するイベントハンドラを追加します。 button や input、a などで最もよく使用しますが、 可視エレメントであればなんでも使うことができます。
要するに、バインディングされているform部品をクリックしたときにそのイベントハンドラを実行します。
clickの実装
<input type="button" data-bind="click: clicked">クリック</input><label data-bind="text: count"></label>
var viewModel = {
count : ko.observable(0),
clicked : function() {
var previousCount = this.count ();
this.count (previousCount + 1);
}
};
ここも特に問題ないと思う。
clickバインディングとcheckedバインディングを同時に使ってみる
さて、ここまではそれぞれ1つの実装だったので問題はないと思います。では、ここからが本題で2つ同時実装してみようと思います。
まずは普通に実装
<label><input type="checkbox" data-bind="checked: isChecked,click:clicked" />テストチェックボックス</label>
<p data-bind="text: isChekd"></p>
var viewModel = {
isChecked: ko.observable(false),
clicked: function() {
// 何かしらの処理
}
};
これで実行してみても上手くいかない。clickは動いていると思いますが、checkedが正常に動作していないはずです。
何がダメなのか。原因は??
knockout.jsの日本語ドキュメントを読んでみました。
(注3) デフォルトのクリックの挙動を許可する
通常、Knockout はクリックイベントによるデフォルトの挙動を抑止します。 これは、もし a (リンク)タグに click バインディングを使用した場合、 例えば、ブラウザはハンドラ関数を呼び出すのみでリンク先への遷移は行いません。 通常は click バインディングにてリンクは、ハイパーリンクではなく ViewModel を操作するための UI 部品として使われるためこのような仕様となっています。
もしもクリックイベントのデフォルトの挙動を行わせたい場合は、 click のハンドラ関数にて true を返却してください。
つまり、正しく動作させたい場合は「tureを返せ」ということらしい。
さっそく実装
var viewModel = {
isChecked: ko.observable(false),
clicked: function() {
// 何かしらの処理
return true; // ここを追加
}
};
今回はうまく動きましたね。
clickバインディングだけを実装してた時には気にも止めていませんでしたが、しっかりとドキュメントは読んだほうがいいなぁと今回のことで思いました。