2013-02-26 62 views
4

我试图用两个下拉列创建一个数据绑定表。但是,右侧下拉菜单中的选项取决于左侧下拉菜单中的选项。例如,假设DropdownA有一个州的列表,DropdownB有一个在该州的城市列表。我的模板看起来是这样的:使用Knockout.js在网格中创建依赖下拉列表

<!-- 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定义依赖下拉列表的各种示例,但是这些示例假定您只有一个源下拉列表(如状态)。在我的情况下,我需要在网格内创建任意数量的下拉。有没有人有一个如何做到这一点的例子?

回答

6

我会把state对象上的城市,然后跟踪它们的行项computed,因为它有一个obserable的状态选择。这里是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; 
    }); 
+0

哦,这看起来很有希望!但是,我必须等到明天我回到办公室才能尝试。 '+ 1'现在! – 2013-02-26 01:25:39

+0

谢谢,这正是我需要的! – 2013-02-26 17:22:12

1

两个解决方案进入我的脑海:

  • 订阅在视图模型DropdownA的observableArray和替换的DropdownB的observableArray城市的范围内时,它改变
  • 使用可观察到的DataContext:使用一个可观察的选项来源,所以你可以在需要的时候改变它。订阅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()); 
+0

你打我,而我正在摆弄= P – Tyrsius 2013-02-26 00:30:59

+0

我是在制造小提琴太:) – 2013-02-26 00:31:28

+0

从我可以告诉,这是行不通的,因为绑定到DropdownB的每一行也会改变。 – 2013-02-26 02:26:18