knockoutのbinding

    この記事は、knockout.js Advent Calendar 2015の４日目の記事です。 先に３日目に目を通すことを推奨しています。
    knockout , knockout-es5 , knockout.punches環境を想定しています。

knockoutのbindingは、HTMLテンプレートに``data-bind="attr:properties"``の形式で書きます。
これまでのサンプルでも、``data-bind="submit:handler"``や、``data-bind="value:model"``といった具合で使ってきました。  
その他にもさまざまなbindingがあるので、それらの一部を紹介します。（ただし詳しいリファレンスは外部リンクです）

* #### value
``data-bind="value:property"``: 解説（[公式](http://knockoutjs.com/documentation/value-binding.html)、[日本語](http://kojs.sukobuto.com/docs/value-binding)）
フォーム要素からの入力(View)　と　ViewModelの値　を紐づけます。

* #### textInput
``data-bind="textInput:property"``: 解説（[公式](http://knockoutjs.com/documentation/textinput-binding.html)、[日本語](http://kojs.sukobuto.com/docs/textinput-binding)）
フォーム要素のinput[type="text"]や、textareaからの入力(View)　と　ViewModelの値　を紐づけます。
valueとの違いは、valueのモデル変更検知のタイミングは、入力コントロールからフォーカスが外れるタイミングなのにたいして、
textInputは、キーが押されたタイミングに変更検知が実行される　という点です。
つまり、``data-bind="textInput:property"``と``data-bind="value:property,valueUpdate:'afterkeydown'`"``と動きが似ています。（←等価であるかどうかは未確認）

* #### checked
``data-bind="checked:property"``: 解説（[公式](http://knockoutjs.com/documentation/checked-binding.html)、[日本語](http://kojs.sukobuto.com/docs/checked-binding)）
``input[type="checkbox"]``や``input[type="radio"]``で、項目が選択されているかをbindingします。
radioボタンであれば、択一なのでpropertyは配列ではなくただの変数を利用しますが、
チェックボックスであれば任意の数が選択されることが想定されているので、propertyには配列[]を指定することになるでしょう。
もちろん、チェックボックスであっても択一の（ON/OFF)であれば、配列である必要はありません。

* #### click
``data-bind="click:handler"``: 解説（[公式](http://knockoutjs.com/documentation/click-binding.html)、[日本語](http://kojs.sukobuto.com/docs/click-binding))
マウス等でのクリックイベントハンドラ：handlerは任意の関数の名前を指定。handlerには、(data , event)が渡されます。

* #### on.click
``data-bind="on.click"``: [解説](https://mbest.github.io/knockout.punches/#expression-based-event-handling)
knockout.punchesによって追加される構文糖衣の、``式ベースのイベントハンドラ``です。
click以外のハンドラも定義することが出来ます。
``data-bind="click:handler"``はhandlerがfunctionである必要がありますが、
``data-bind="on.click:expression"``はexpressionに任意の式が書けます。　式にfunctionの呼び出しコードもかくことができるので、
``data-bind="on.click:handler(parameter)"``のように、handlerに任意の引数を渡すこともできます。

* #### attr
``data-bind="attr:properties"``: 解説（[公式](http://knockoutjs.com/documentation/attr-binding.html)、[日本語](http://kojs.sukobuto.com/docs/attr-binding))
htmlの属性(attr)へdata-bindを設定するものです。
例えば、``data-bind="attr:{src:'http://example.com/'+imgfile}"``とすれば、
imgのsrcを動的に設定できます。
ただし、knockout.punchesを導入している際にはimgのsrcなど、外部リソースへの参照用くらいにしか使わないと思います。
なぜなら、```html <i class="fa fa-{{icon}}"></i>```の構文糖衣が利用可能だからです。
これは、
``<i data-bind="attr:{'class':'fa fa-'+icon}"></i>``と等価です。

* #### style
``data-bind="style:{}"``: 解説（[公式](http://knockoutjs.com/documentation/style-binding.html)、[日本語](http://kojs.sukobuto.com/docs/style-binding)）
　htmlのstyle属性へのdata-bindを設定するものです。
例えば、``data-bind="style:{color:gender=='M'?'blue':'red'}"``とすれば、
viewmodelのgenderがMであれば、文字をblueに、そうでなければredに、という感じで利用します。

------------------------------------------------------------------------

これらの（一部）をつかった[サンプルは、こんな感じ](http://jsfiddle.net/MKGaru/8jtfcsze/)になります。

```html:index.html
<h1>User Info</h1>
<dl>
    <dt>指名</dt>
    dd><input type="text" data-bind="value:name,style:{color:gender=='M'?'blue':'red'}" /></dd>
    
    <dt>年齢</dt>
    <dd><input type="number" data-bind="value:age" /></dd>
    
    <dt>性別</dt>
    <dd>
        <label><input type="radio" name="gender" value="M" data-bind="checked:gender" />男</label>
        <label><input type="radio" name="gender" value="F" data-bind="checked:gender" />女</label>
        <label><input type="radio" name="gender" value="O" data-bind="checked:gender" />他</label>
    </dd>
    
    <dt>属性</dt>
    <dd>
        <label><input type="checkbox" data-bind="checked:married" />既婚</label>
    </dd>
</dl>

<hr>
JSONにすると・・・・<br>
<textarea data-bind="text:ko.toJSON($data,null,2)" rows="6"></textarea>
```

```js:script.js
function UserInfo(options){
    this.name = options.name;
    this.age = options.age;
    this.gender = options.gender;
    this.married = options.married;
    ko.track(this);
}

ko.punches.enableAll();
ko.applyBindings(new UserInfo({
    name: "山田",
    age:36,
    gender:"M",
    married: true
}));
```