Knockoutを使って ViewModelのコレクション(配列)のプロパティをforeach バインディングを使ってバインドし、マークアップを生成する方法の覚書を記載します。また、 Withバインディングを使用して単一のオブジェクトにバインドするサンプルも記載します。Withバインディングを使用すると バインド中のコンテキストオブジェクトからのフルパスを記載する手順を省くことができます。

検証に使った KnockoutJS のバージョンは 3.3 です。

1. foreach バインディングとwith バインディングを使用する

foreachバインディングを使用することで、ViewModelの配列オブジェクトを要素にバインドし、繰り返すマークアップを生成できます。foreachバインディングは htmlの要素だけでなく、コメントを使ってバインドの設定を行うこともできます。下記に簡単なサンプルを記載します。コメントを使ってバインディングする場合は <!-- ko --> と <!-- /ko --> を使用します。html要素にバインドする場合は、通常のtext, htmlバインディングする場合と同じです。

<!DOCTYPE html>
<html lang="ja">
<head>
    <title>ループ処理</title>
</head>
<body>
    <div>
        <h1>foreachバインディングを要素に適用</h1>
        <ul data-bind="foreach: relatedUrls">
            <li><a data-bind="attr:{ href:url}"><span data-bind="text:text"></span></a></li>
        </ul>
        <h1>foreachバインディングをコメントで適用</h1>
        <ul>
            <!-- ko foreach: relatedUrls-->
            <li><a data-bind="attr:{ href:url}"><span data-bind="text:text"></span></a></li>
            <!-- /ko -->
        </ul>
        <h1>with バインディング</h1>
        <ul data-bind="with: account">
            <li data-bind="text: name"></li>
            <li data-bind="text: $parent.format(birthDay)"></li>
        </ul>
    </div>
    <script type="text/javascript" src="/Scripts/knockout-3.3.0.js"></script>
    <script type="text/javascript">
        function viewModel(name) {
            var self = this;

            self.relatedUrls = [
                { url: "http://www.bing.com", text: "Bing" },
                { url: "http://www.yahoo.co.jp", text: "Yahoo" },
                { url: "http://www.google.co.jp", text: "google" }
            ];

            self.account = {
                name: "KO 太郎",
                birthDay: new Date(2004, 2, 10)
            };

            self.format = function(date){
                return date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate();
            };
        }
        var vm = new viewModel();
        ko.applyBindings(vm)
    </script>

</body>
</html>

上記サンプルでは、 with バインディングも使っています。with バインディングは foreach と異なり、単一のオブジェクトにバインドします。サンプルのように使うことでコンテキストオブジェクトが withバインディングで指定したオブジェクトに切り替わるので account.name や account.birthDay のようにパスを記述する処理を省略して name, birthDay とバインディングするプロパティを指定できるようになります。

サンプルではそのほかのトピックとして KnockoutJSで提供される $parent というバインディングコンテキストのプロパティを使用しています。 $parent プロパティは カレントコンテキストのビューモデルオブジェクトの親のオブジェクトを表します。サンプルで$parentを使用しているときのコンテキストのビューモデルのオブジェクトは account ですので $parentを使用することで ビューモデルの format 関数が呼び出されるようになります。

バインディングコンテキストの詳細は KnockoutJS の公式ページを参照してください。$data, $root, $parent, $parents など様々なプロパティが用意されています。

Binding context
http://knockoutjs.com/documentation/binding-context.html

foreach バインディングには 要素をバインドした後に何らかの処理をするようなコールバック関数(afterRender/afterAdd/beforeRemove/beforeMove/afterMove)が用意されています。foreach は様々な機能がありますので詳細は次のURLを参照してください。

The "foreach" binding
http://knockoutjs.com/documentation/foreach-binding.html

2.まとめ

説明は以上です。  KnockoutJSを使ってみた - 簡単なバインディングを行ってみる と組み合わせるといろいろなことができるようになります。