読者です 読者をやめる 読者になる 読者になる

からめもぶろぐ。

ワタシ SharePoint チョット デキル

knockout.js でページの再読み込みに対応する

前回の記事の続きです。

blog.karamem0.jp

前回の状態だと、ページを再読み込みすると、検索結果がすべて消えて初期状態に戻ってしまうという問題点がありました。それではやはり使い勝手が悪いので、対応を考えてみたいと思います。
簡単に言ってしまうと、データをどこかに保存しておけばいいのですが、とりあえずサーバー側に保存してみます。

サンプル コード

Controllers/HomeController.cs

前回からの変更点として、検索されたときにパラメーターをセッションに入れているのと、初期表示でセッションにデータがあれば ViewBag に入れるところが追加されています。

    public class HomeController : Controller {

       public ActionResult Index() {
            // セッションがあれば ViewBag に入れる
            var person = this.Session["Person"] as Person;
            if (person != null) {
                this.ViewBag.Person = person;
            }
            return View();
        }

        [HttpPost()]
        public JsonResult Index(Person person) {
            // パラメーターをセッションに格納する
            this.Session["Person"] = person;

            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(person.Id) || x.Id == person.Id)
                    .Where(x => string.IsNullOrEmpty(person.Name) || x.Name.Contains(person.Name))
                    .Where(x => person.Age == null || x.Age == person.Age)
            );
        }
    }

Views/Home/Index.cshtml

ViewBag に入れられたパラメーターを Json.Encode ヘルパーメソッドで JavaScript から読めるようにします。あとはそれをフォームに突っ込んで再検索してしまいます。

<script type="text/javascript">
    $(function () {
        var viewModel = {
            items: ko.observableArray([]),
            search: function () {
                var self = this;
                var param = {};
                $("form :input").each(function () {
                    var name = $(this).attr("name");
                    var val = $(this).val();
                    param[name] = val;
                });
                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);

        // ViewBag からデータをもらう
        var person = @Html.Raw(Json.Encode(ViewBag.Person));
        if (person != null) {
            // フォームにデータを入れる
            $("form :input").each(function () {
                var name = $(this).attr("name");
                var val = person[name];
                if (val != null) {
                    $(this).val(val);
                }
            });
            // 再検索
            viewModel.search();
        }
    });
</script>

これで再読み込みをしても元の状態を復元することができました。