"click" バインディング
用途
click
バインディングは関連付けられた DOM エレメントがクリックされたときに、
指定した JavaScript 関数を実行するイベントハンドラを追加します。
button
や input
、a
などで最もよく使用しますが、
可視エレメントであればなんでも使うことができます。
例
<!-- View --> <div> <span data-bind="text: numberOfClicks"></span> 回クリックしました。 <button data-bind="click: incrementClickCounter">クリックして下さい</button> </div>
// ViewModel var viewModel = { numberOfClicks : ko.observable(0), incrementClickCounter : function() { var previousCount = this.numberOfClicks(); this.numberOfClicks(previousCount + 1); } };
ボタンをクリックするたび、ViewModel の incrementClickCounter()
が実行されます。
incrementClickCounter()
は ViewModel の状態を変化させるので、結果的に UI が更新されます。
パラメタ
-
主パラメタ
エレメントの
click
イベントにバインドしたい関数どんな JavaScript 関数も使用できます。ViewModel の関数である必要は、必ずしもありません。
click: someObject.someFunction
のように書くことで、どんなオブジェクトの関数も参照できます。 -
追加パラメタ
なし
(注1) ハンドラ関数に引数として“現在のアイテム”が渡される
ハンドラを呼び出す際、Knockout は第一引数として現在のモデルを渡します。 これは、特に配列の各要素を表示し、さらにどのアイテムの UI がクリックされたのかを知る必要があるときに便利です。
<ul data-bind="foreach: places"> <li> <span data-bind="text: $data"></span> <button data-bind="click: $parent.removePlace">Remove</button> </li> </ul> <script type="text/javascript"> function MyViewModel() { var self = this; self.places = ko.observableArray(['London', 'Paris', 'Tokyo']); // 第一引数として現在のアイテムが渡されるため、どれを削除すべきかがわかる self.removePlace = function(place) { self.places.remove(place) } } ko.applyBindings(new MyViewModel()); </script>
上記サンプルのポイントは2つあります:
-
foreach
やwith
の内部のように、 ネストされた バインディング・コンテキスト の中でルート ViewModel やその他親のコンテキストのハンドラ関数を呼び出す場合、 ハンドラ関数を示すために$parent
$root
といったプレフィックスを使う必要があります。 -
ViewModel にて、
this
の別名としてself
変数を定義すると便利です。this
を再定義することで、イベントハンドラや Ajax リクエストのコールバックで発生する 問題を事前に回避 することができます。
(注2) イベントオブジェクトにアクセスする、またはさらなる引数を渡す
場合によっては、クリックイベントの DOM イベントオブジェクトにアクセスする必要がありますよね。 Knockout は、次の例のようにイベントオブジェクトを第二引数として関数に渡します。
<button data-bind="click: myFunction"> ここをクリック </button> <script type="text/javascript"> var viewModel = { myFunction: function (data, event) { if (event.shiftKey) { // Shift キーが押されていた時のアクション } else { // 通常のアクション } } }; ko.applyBindings(viewModel); </script>
さらに引数を渡す方法として、まずハンドラを、引数を受け渡す関数リテラルでラップする方法があります。
<button data-bind="click: function(data, event) { myFunction('引数1', '引数2', data, event) }"> ここをクリック </button>
Knockout は関数リテラルにデータとイベントオブジェクトを渡すため、ハンドラに渡すことができるということになります。
別の方法として、関数リテラルを View に記述するのは避けたいのならば bind 関数を使いましょう。 次のように、関数を呼び出す際の引数を指定することができます。
<button data-bind="click: myFunction.bind($data, '引数1', '引数2')"> ここをクリック </button>
(注3) デフォルトのクリックの挙動を許可する
通常、Knockout はクリックイベントによるデフォルトの挙動を抑止します。
これは、もし a
(リンク)タグに click
バインディングを使用した場合、
例えば、ブラウザはハンドラ関数を呼び出すのみでリンク先への遷移は行いません。
通常は click
バインディングにてリンクは、ハイパーリンクではなく
ViewModel を操作するための UI 部品として使われるためこのような仕様となっています。
もしもクリックイベントのデフォルトの挙動を行わせたい場合は、
click
のハンドラ関数にて true
を返却してください。
(注4) イベントバブリングを抑止する
通常、Knockout はクリックイベントが上位の要素のイベントハンドラにバブリングすることを許可します。
例えば、ある要素とその親要素がどちらも click
イベントをハンドリングするとします。
このときこの要素がクリックされると、両方の要素にてハンドラが呼び出されます。
必要であれば、 clickBubble
という追加バインディングに false
を指定することでバブリングを抑止することができます。
<div data-bind="click: myDivHandler"> <button data-bind="click: myButtonHandler, clickBubble: false"> ここをクリック </button> </div>
この場合通常であれば myButtonHandler
が最初に呼び出され、
クリックイベントは myDivHandler
に遡及します。
しかし、付与された clickBubble
バインディングの false
指定によってイベントの遡及は
myButtonHandler
を通過後に止まります。
依存
Knockout コアライブラリ以外、なし。