knockout.js リストのバインディング
knockout.js を使って ajax 通信を使ったリストのバインディングを行う方法です。
既にいろんなところに情報がありますが、覚書きとして・・
Html
とあるボタンが押されたら、ニュースを取得してリストに表示する、という実装を行います。
Html は以下の通りです。
<div class="view-news" data-get-url="<%= Url.Action("GetNews", "NewsApi") %>"> クリックでニュースを表示します。 </div> <ul data-bind="foreach: newsList" class="news-list"> <li data-bind="attr: { 'data-id' : Id }"> <div data-bind="text: DateText"></div> <div data-bind="text: Content"></div> </li> </ul>
属性のバインディング
属性の値にバインドしたい時は、下のように書きます。
属性名を独自の名前にしたい場合は、'' で囲む必要があります。
data-bind="attr: { 'data-id' : Id }"
公式のThe attr bindingに説明があります。
Json を提供する API を用意
ASP.NET MVC で用意しました。
本当は MVC4 の WEB API を使いたいところですが、プロジェクトのバージョンが古かったので(; ;) 、普通のアクションメソッドで作成しました。
/// <summary> /// ニュースを取得します /// </summary> /// <param name="maxCount"></param> /// <returns></returns> [HttpGet] [Authorize] public ActionResult GetNews(int maxCount) { var response = _newsService.GetNews(maxCount); return Json(response.News, JsonRequestBehavior.AllowGet); }
GET で Json を取得するときは、JsonRequestBehavior.AllowGet の指定を忘れがち。。
取得できる Json は、このような感じです。
[{"Id":41,"DateText":"12/21(金)","Content":"今日ReSharperを買いました!"},{...//続く}]
各項目名は、Html で書いた
data-bind="text: DateText"(←例えばこのDateText)
の名前と同じにします。
JavaScript
JavaScript 以下の通りです。
$(function () { function viewModel() { var self = this; self.newsList = ko.observableArray(); } var viewModel = new viewModel(); ko.applyBindings(viewModel); $(".view-news").live('click', function () { //ニュースを表示するボタンがクリックされたら //APIを取得するためのURLを取得 var url = $(this).attr("data-get-url"); $.ajax({ type: "GET", url: url, data: { maxCount: 5 }, dataType: "json", cache: false, success: function (data) { viewModel.newsList(data); } }); });
viewModel の newsList という名前は、Html で ul 要素に書いた
data-bind="foreach: newsList" (←例えばこの newsList)
名前と同じにします。
$(...).live(...) という書き方は古いみたいですが、
$(...)on(...) でかくと、新しく生成された要素に対しては適応されず・・・。
適応されます。$(document).on('click',要素,function() {... という書き方をすると、新しく生成された要素にも適応します。参照:jQuery 1.7の on() off()について調べてみた
おしまい
2012年12月14日に、公式サイトを日本語訳したKnockout 日本語ドキュメント
というサイトが公開されています!便利!