I'm attempting to create a data-bound table with two dropdown columns. However, the options available in the right dropdown are dependent on what's selected in the left dropdown. For example, imagine DropdownA
has a list of states, and DropdownB
has a list of cities in that state. My template looks like this:
<!-- 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 -->
Right now, DropdownB
shows every item in $root.AllCities
. However, I want it to only show cities that have a State
property of whatever value is selected in DropdownA
.
I've found various examples online on how to define dependent dropdowns using a puted observable, however these examples assume you only have a single source dropdown (such as State). In my case, I need to create an arbitrary number of dropdown pairs within the grid. Does anyone have an example of how this can be done?
I'm attempting to create a data-bound table with two dropdown columns. However, the options available in the right dropdown are dependent on what's selected in the left dropdown. For example, imagine DropdownA
has a list of states, and DropdownB
has a list of cities in that state. My template looks like this:
<!-- 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 -->
Right now, DropdownB
shows every item in $root.AllCities
. However, I want it to only show cities that have a State
property of whatever value is selected in DropdownA
.
I've found various examples online on how to define dependent dropdowns using a puted observable, however these examples assume you only have a single source dropdown (such as State). In my case, I need to create an arbitrary number of dropdown pairs within the grid. Does anyone have an example of how this can be done?
Share Improve this question asked Feb 26, 2013 at 0:07 Mike ChristensenMike Christensen 91.7k51 gold badges219 silver badges347 bronze badges2 Answers
Reset to default 6I would put the cities on the state
object, and then track them as a puted
on the row item, since it will have an obserable for the state selection. Here is 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.puted(function(){
if(self.state() == "" || self.state().cities == undefined)
return [];
return self.state().cities;
});
Two solution es into my mind:
- subscribe to the observableArray of
DropdownA
in the viewmodel and replace the range of the cities in the observableArray ofDropdownB
whenever it changes - use an observable datacontext: use an observable as the options source so you can change it when you need too. Subscribe to
DropdownA
as in the first one and replace the entire city collection whenever it changes
I would choose the second one, because that's more clean.
here is a jsfiddle sample I made for you.
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());
Then it's easy to use this concept in multiple rows: http://jsfiddle/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());