2013-02-26 6 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.

Я нашел различные примеры онлайн о том, как определить зависимые выпадающие списки с использованием вычисленного наблюдаемого, однако эти примеры предполагают, что у вас есть только один раскрывающийся список источников (например, состояние). В моем случае мне нужно создать произвольное число выпадающих списков пар в сетке. Есть ли у кого-нибудь пример того, как это можно сделать?

ответ

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> 

ЯШ:

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' сейчас! –

+0

Спасибо, это было именно то, что мне нужно! –

1

Два решение приходит мне в голову:

  • подписаться на observableArray из DropdownA в ViewModel и заменить ряд городов в observableArray из DropdownB всякий раз, когда он меняет
  • использовать наблюдаемую 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

+0

я делал скрипку тоже :) –

+0

Из того, что я могу сказать , это не сработает, потому что каждая строка, связанная с DropdownB, также изменится. –

Смежные вопросы