からめもぶろぐ。

SharePoint が得意なフレンズなんだね!すごーい!

knockout.js を使って検索をしてみる

前の記事とだいぶ時間が空いてしまいましたが、引き続き knockout.js を弄ってみます。

blog.karamem0.jp

今回は検索をしてみたいと思います。

サンプル コード

Models/Person.cs

簡単な Model を作成します。

    public class Person {

        public string Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

    }

Controllers/HomeController.cs

Controller の実装は、単純に検索クエリを受け取って結果を JSON で返しています。

    public class HomeController : Controller {

        public ActionResult Index() {
            return this.View();
        }

        [HttpPost()]
        public JsonResult Index(string id, string name, int? age) {
            var data = new[] {
                new Person() { Id = "1", Name = "佐藤太郎", Age = 30, },
                new Person() { Id = "2", Name = "山田次郎", Age = 15, },
                new Person() { Id = "3", Name = "高橋三郎", Age = 60, },
                new Person() { Id = "4", Name = "田中四郎", Age = 55, },
                new Person() { Id = "5", Name = "鈴木五郎", Age = 45, },
            };
            return this.Json(
                data.Where(x => string.IsNullOrEmpty(id) || x.Id == id)
                    .Where(x => string.IsNullOrEmpty(name) || x.Name.Contains(name)) 
                    .Where(x => age == null || x.Age == age)
            );
        }
    }

Views/Home/Index.cshtml

View の実装です。knockout.js を使って検索ボタンのクリックイベントに search メソッドを連結します。jQuery の each メソッドでフォームの要素をぶん回して値を取ってくるようにしています。なんとなく汎用的にはなっていますが、ここはもう少しうまいやり方があるのかも。
(追記) serializeArray メソッドというのが使えるんですね。

@model MvcApplication1.Models.Person
@{
    ViewBag.Title = "ホーム ページ";
}
@using (Html.BeginForm()) { 
    <table>
        <tr>
            <td><span class="editor-label">@Html.LabelFor(model => model.Id)</span></td>
            <td><span class="editor-field">@Html.TextBoxFor(model => model.Id)</span></td>
        </tr>
        <tr>
            <td><span class="editor-label">@Html.LabelFor(model => model.Name)</span></td>
            <td><span class="editor-field">@Html.TextBoxFor(model => model.Name)</span></td>
        </tr>
        <tr>
            <td><span class="editor-label">@Html.LabelFor(model => model.Age)</span></td>
            <td><span class="editor-field">@Html.TextBoxFor(model => model.Age)</span></td>
        </tr>
    </table>
    <input type="button" value="検索" data-bind="click: search" />
    <div data-bind="foreach: items">
        <div>
            <span data-bind="text: Id"></span>
            <span data-bind="text: Name"></span>
            <span data-bind="text: Age"></span>
        </div>
    </div>
}
<script type="text/javascript">
    $(function () {
        var viewModel = {
            items: ko.observableArray([]),
            search: function () {
                var self = this;
                var param = $("form :input").serializeArray();
                var callback = function (data) {
                    self.items.removeAll();
                    $.each(data, function (i, e) {
                        self.items.push(e);
                    });
                };
                $.post("@Url.Action("Index")", param, callback, "json");
            }
        };
        ko.applyBindings(viewModel);
    });
</script>

実行

名前で検索してみます。

f:id:karamem0:20160625225624p:plain

ちゃんと検索できました!

f:id:karamem0:20160625225635p:plain

ちなみに何も入れなければ全部出てきます。

f:id:karamem0:20160625225644p:plain