使用ASP.NET和KnockoutJS从另一个组合框填充一个组合框

时间:2013-08-19 04:19:03

标签: asp.net knockout.js combobox

我知道之前有人问过这个问题,但是我已经有好几个小时了,我找不到可行的解决方案。总结一下,我从服务器(C#)收到一个JSON字符串,如下所示:

function CallFromServer() {
$.ajax({
    type: "POST",
    async: false,
    url: "Default.aspx/GetTest",
    data: "{ }",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (msg) {
            locationsList = jQuery.parseJSON(msg.d);
        }
    });
};

漂亮的香草,对吗? locationsList的每个条目由一个字符串组成,该字符串是一个州和另一个列表,由该给定状态的城市组成。我对KnockoutJS很新(而且它甚至不是我的项目,我只是做一个小自由职业者),所以在搞砸了一段时间之后,我得出了关于如何填充组合框的结论:

HTML:

<select id="stateSelect" onchange="GetCities()" style="background-color:#69bed2; width:50px;" data-placeholder="..."
        data-bind="options: stateValue" name="state" class="chosen-select" tabindex="1">
</select>

<select id="citySelect" style="background-color:#69bed2; width:143px;" data-placeholder="Select a state"
              data-bind="options: cityValue" name="city" class="chosen-select" tabindex="2">
</select>

JS:

function CalculatorViewModel()
{
    var self = this;
    CallFromServer(); //Mine
    GetStates(); //Mine

    self.percentBonus = ko.observable(3);
    self.typedValue = ko.observable("0");
    self.bonusValue = ko.observable('');
    self.messageValue = ko.observable("");
    self.stateValue = ko.observableArray(stateArray); //Mine
    self.cityValue = ko.observableArray(cityArray); //Mine

    (...) //A lot of stuff
}

什么没有被评论为“我的”几乎已经存在,并且随着对KOJS文档的一些阅读,我用它来试图实现我想要的。

好的,现在让我们来看看它的要点。有人可能会注意到我使用了

onchange="GetCities()

在第一个选择中。这是代码:

function GetCities() {
    cityArray.clear();
    cityArray[0] = '';
    var currentState = $('#stateSelect :selected').text();
    $.each(locationsList, function (i, e) {
        if (e.stateName == currentState) {
            $.each(e.cityList, function (j, city) {
                cityArray[j] = e.cityList[j].cityName;
            });
        }
    });
};

如所预期的,每当更改状态时引发此onChange事件时,self.cityArray会将其自身更新为正确的值。但是,无论如何,它所绑定的组合框都不会刷新。我已经阅读了很多关于不同方法的内容,但我觉得我对这种方法非常接近,从头开始不是一种选择。

有没有人对我在这里缺少什么有任何想法?

顺便说一句,不要担心我的stateArray绑定,它的工作正常。在选择州之后渲染cityArray提供的新选项是令人烦恼的事情。

1 个答案:

答案 0 :(得分:2)

我认为你可能会对Knockout如何运作感到困惑,它可能有助于完成the turorials。你似乎做了两件违背KO想法的事情:

  • 不要像这样直接连接onchange事件,而是使用一些Knockout构造(例如订阅);
  • 您似乎正在清除并重新填充cityArray而不是cityValue可观察数组;用户界面只会响应后者的变化

此外,您还需要:

  • selectedOptions绑定将observable绑定到选定状态

我至少会根据各自的顺序提出一些更改:

<select id="stateSelect" 
        style="background-color:#69bed2; width:50px;" 
        data-placeholder="..."
        data-bind="options: stateValue, selectedOptions: selectedStates" 
        name="state" 
        class="chosen-select" 
        tabindex="1">
</select>

视图模型需要扩展一些东西来保存状态选择:

function CalculatorViewModel()
{
    // Added:
    self.selectedStates = ko.observableArray([]);;       
}

同时删除onchange直接事件接线。用这些行替换它,订阅selectedOptions:

// Use a KO subscription:
self.selectedStates .subscribe(function(newStateValue) {

    // Clear the *observable* array
    self.cityValues.removeAll();

    $.each(locationsList, function (i, e) {
        if (e.stateName == newStateValue) {
            $.each(e.cityList, function (j, city) {
                // Push into the observable array so the UI gets updated
                self.cityValues.push(e.cityList[j].cityName);
            });
        }
    });
});

以下是a fiddle演示如何运作。