选择列表不会刷新

时间:2016-02-25 13:37:11

标签: javascript knockout.js knockout-3.0

我试图用ASP.net MVC4找出knockoutjs(版本3.4)

我有以下视图模型:

function ViewModel(data) {
    var self = this;
    self.filteredColumnsArray;
    var viewsArray = buildSimpleViewsArray(data.AllViews);
    self.views = ko.observableArray(viewsArray);
    self.selectedView = ko.observable(viewsArray[0]);
    self.newView = ko.observable("");

    var columnsArray = ko.observableArray(data.AllColumns);
    self.filteredColumns = ko.observableArray(self.filteredColumnsArray);
    self.columnsToAdd = ko.observableArray();

    self.selectedView.subscribe(function () {
        self.filteredColumnsArray = ko.utils.arrayFilter(columnsArray(), function (column) {
            return column.ViewId === getViewId(self.selectedView());
        });
        self.filteredColumns = ko.observableArray(self.filteredColumnsArray);
    });

    function getViewId(viewName) {
        var id;
        var index;
        for (index = 0; index < data.AllViews.length; ++index)
        {
            if (data.AllViews[index].Name === viewName) {
                id = data.AllViews[index].ViewId;
                }
        }
        return id;
    };

    function buildSimpleViewsArray(objectArray) {
        var simpleArray = new Array;
        for (var o in objectArray) {
            simpleArray.push(objectArray[o].Name);
        }
        return simpleArray;
    }

    function buildSimpleColumnsArray(objectArray) {
        var simpleArray = new Array;
        for (var o in objectArray) {
            simpleArray.push(objectArray[o].Heading);
        }
        return simpleArray;
    }

    self.addView = function () {
        if ((self.newView() != "") && (self.views.indexOf(self.newView()) < 0)) // Prevent blanks and duplicates
            self.views.push(self.newView());
        self.newView(""); // Clear the text box
    };

    self.removeSelected = function () {
        this.views.remove(self.selectedView);
        this.selectedView = "";
    };

    self.saveToDatabase = function () {
        this.views.remove(self.selectedView);
        this.selectedView = "";
    };
};

和这个观点:

@model TVS.ESB.BamPortal.Website.Models.UserPrefsViewModel
@using System.Web.Script.Serialization
@{
    ViewBag.Title = "User Preferences";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>@ViewBag.Title</h2>
@{  string data = new JavaScriptSerializer().Serialize(Model); }

<div id="ViewsAndColumns" class="container">
    <div class="row">
        <div id="Views" class="col-md-6 pull-left">
            <span class="label-primary">Views</span>
            <br />
            <table>
                <tr>
                    <td>
                        <span>New View:</span>
                    </td>
                    <td>
                        <input style="width:100px" class="input-sm" data-bind='value:newView, valueUpdate: "afterkeydown"' />
                        <button class="btn-default" data-bind="click:addView, enable:newView().length > 0">Add View</button>
                    </td>
                </tr>
                <tr>
                    <td>
                        <span>Views:</span>
                    </td>
                    <td>
                        <select style="width:100px" size="5" data-bind="options:views, value:selectedView"> </select>
                        <button class="btn-default" data-bind="click:removeSelected">Remove</button>
                    </td>
                </tr>
                <tr>
                    <td>
                        <button class="btn-danger" data-bind="click:saveToDatabase">Save to Database</button>
                    </td>
                </tr>
            </table>
        </div>
        <div id="Columns" class="col-md-6 pull-right">
            <span class="label-primary">Columns</span>
            <br />
            <table>
                <tr>
                    <td>
                        @*<select multiple="multiple" data-bind="options:filteredColumns, selectedOptions:columnsToAdd"></select>*@
                        <select multiple="multiple" data-bind="options:filteredColumns"></select>
                    </td>
                </tr>
            </table>
        </div>
    </div>
</div>



@section Scripts {
    <script src="~/KnockoutVM/UserPrefs.js"></script>

    <script type="text/javascript">
        var vm = new ViewModel(@Html.Raw(data));
        ko.applyBindings(vm, document.getElementById("UserPrefsDiv"));
    </script>
}

VM接收此数据:

{
  "ViewId": 0,
  "Name": null,
  "AllColumns": [
    {
      "ColumnId": 5,
      "ViewId": 5,
      "Heading": "ErpColumn1"
    },
    {
      "ColumnId": 6,
      "ViewId": 5,
      "Heading": "ErpColumn2"
    },
    {
      "ColumnId": 7,
      "ViewId": 6,
      "Heading": "CceColumn1"
    },
    {
      "ColumnId": 8,
      "ViewId": 6,
      "Heading": "CceColumn2"
    }
  ],
  "VisibleColumns": [],
  "AllViews": [
    {
      "ViewId": 5,
      "Name": "erp",
      "Columns": [
        {
          "ColumnId": 5,
          "ViewId": 5,
          "Heading": "ErpColumn1"
        },
        {
          "ColumnId": 6,
          "ViewId": 5,
          "Heading": "ErpColumn2"
        }
      ]
    },
    {
      "ViewId": 6,
      "Name": "cce",
      "Columns": [
        {
          "ColumnId": 7,
          "ViewId": 6,
          "Heading": "CceColumn1"
        },
        {
          "ColumnId": 8,
          "ViewId": 6,
          "Heading": "CceColumn2"
        }
      ]
    }
  ]
}

在我看来,他们是2个多行选择框,视图。当用户从视图列表中选择一行时,我希望列表仅显示具有相应视图ID的列。

我想我几乎有这个工作。使用Chrome开发工具,我在selectedView.subscribe函数中放置了一个断点,我可以看到 filteredColumnsArray 已正确填充。然后将其分配给可观察数组 filteredColumns ,该数组绑定到视图中的第二个选择列表。我的问题是,第二个清单没有像我期望的那样刷新。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

问题可能是因为您要创建一个新的ko.observableArray()filteredColumns,并且这不会绑定到视图,而是要更改&#34;值&#34;该属性更改ko.observable的值。

Ex Insted this:

var x = ko.observable("1st value");
x = ko.observable("2nd value");

这样做:

var x = ko.observable("1st value");
x("2nd value");

subscribe的{​​{1}}处尝试此操作:

selectedView