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

Creating dependent dropdowns in a grid using Knockout.js

本文关键字:创建 依赖 下拉列表 网格 Knockout js 使用      更新时间:2023-09-26

我正试图创建一个包含两个下拉列的数据绑定表。但是,右侧下拉列表中可用的选项取决于左侧下拉列表中选择的内容。例如,假设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中选择什么值。

我在网上找到了各种关于如何使用计算的可观察项定义依赖下拉列表的示例,但是这些示例假设您只有一个源下拉列表(如State(。在我的情况下,我需要在网格中创建任意数量的下拉。有人举过这样做的例子吗?

我会将城市放在state对象上,然后将它们作为行项目上的computed进行跟踪,因为它将具有可观察的状态选择。这是一把小提琴

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;
    });

我想到了两个解决方案:

  • 在视图模型中订阅DropdownA的observableArray,并随时替换DropdownB的observaleArray中的城市范围
  • 使用可观察的数据上下文:使用可观察作为选项源,这样您也可以在需要时更改它。与第一个一样订阅DropdownA,并在其更改时替换整个城市集合

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

这是我为你做的一个jsfiddle样品。

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());