最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Creating dependent dropdowns in a grid using Knockout.js - Stack Overflow

programmeradmin3浏览0评论

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 badges
Add a ment  | 

2 Answers 2

Reset to default 6

I 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 of DropdownB 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());
发布评论

评论列表(0)

  1. 暂无评论