使用Knockout.js在网格中创建依赖的下拉列表

时间:2013-02-26 00:07:43

标签: javascript knockout.js

我正在尝试使用两个下拉列创建数据绑定表。但是,右下拉列表中可用的选项取决于左下拉列表中选择的内容。例如,假设DropdownA包含状态列表,DropdownB包含该州的城市列表。我的模板如下所示:

<!-- ko foreach: MeasurementInfoPlans -->
<tr>
   <td><select id="DropdownA" data-bind="options: $root.AllStates, optionsValue: 'State', optionsText: 'Name', value: StateId"></select></td>
   <td><select id="DropdownB" data-bind="options: $root.AllCities, optionsValue: 'City', optionsText: 'Name', value: CityId"></select></td>
</tr>
<!-- /ko -->

目前,DropdownB会显示$root.AllCities中的所有项目。但是,我希望显示在State中选择具有DropdownA属性的城市。

我在网上找到了关于如何使用计算的observable定义依赖下拉列表的各种示例,但是这些示例假设您只有一个源下拉列表(例如State)。就我而言,我需要在网格中创建任意数量的下拉。有没有人举例说明如何做到这一点?

2 个答案:

答案 0 :(得分:6)

我会将城市放在state对象上,然后在行项目上将其作为computed进行跟踪,因为它对于状态选择非常有用。这是a fiddle

HTML:

<select data-bind="options: $parent.states,
                   optionsText: 'name',
                   value: state"></select>
<select data-bind="options: cities, value: city"></select>

JS:

    self.state = ko.observable("");
    self.city = ko.observable("");
    self.cities = ko.computed(function(){
        if(self.state() == "" || self.state().cities == undefined)
            return [];
        return self.state().cities;
    });

答案 1 :(得分:1)

我想到了两个解决方案:

  • 在viewmodel中订阅DropdownA的observableArray,并在DropdownB更改时更改observableArray中的城市范围
  • 使用可观察的datacontext:使用observable作为选项源,以便在需要时也可以更改它。订阅DropdownA和第一个一样,并在更改时替换整个城市集合

我会选择第二个,因为那更干净。

here is a jsfiddle sample我为你做了。

HTML:

<select data-bind="options: dropdownA, value: dropdownAValue">
</select>
<select data-bind="options: dropdownB">
</select>

JS:

var viewModel = function() {
    var _this = this,
        dataSource1,
        dataSource2;

    dataSource1 = ["Hello"];
    dataSource2 = ["World"];

    _this.dropdownA = ko.observableArray(["A", "B"]);
    _this.dropdownB = ko.observable(dataSource1);
    _this.dropdownAValue = ko.observable();

    _this.dropdownAValue.subscribe(function() {
        if (_this.dropdownAValue() == "A") {
            _this.dropdownB(dataSource1);   
        } else {
            _this.dropdownB(dataSource2);   
        }
    });
};

ko.applyBindings(new viewModel());

然后很容易在多行中使用这个概念:http://jsfiddle.net/jGRQH/

HTML:

<table data-bind="foreach: rows">
    <tr>
       <td>
            <select data-bind="options: $root.dropdownA, value: dropdownAValue">
            </select>
        </td>
        <td>
            <select data-bind="options: dropdownB">
            </select>
        </td>
    </tr>
</table>

JS:

var rowViewModel = function(dataSource1, dataSource2) {
    var _this = this;

    _this.dropdownB = ko.observable(dataSource1);
    _this.dropdownAValue = ko.observable();

    _this.dropdownAValue.subscribe(function() {
        if (_this.dropdownAValue() == "A") {
            _this.dropdownB(dataSource1);   
        } else {
            _this.dropdownB(dataSource2);   
        }
    });
};

var mainViewModel = function() {
    var _this = this,
        dataSource1,
        dataSource2,
        addRow;

    dataSource1 = ["Hello"];
    dataSource2 = ["World"];

    addRow = function () {
        _this.rows().push(new rowViewModel(dataSource1, dataSource2));
    };

    _this.rows = ko.observableArray();

    _this.dropdownA = ko.observableArray(["A", "B"]);

    addRow();
    addRow();
    addRow();
};

ko.applyBindings(new mainViewModel());