Я пытаюсь получить четыре каскадных выпадающие с помощью knockout.js:Используйте knockout.js для 4 каскадных выпадающих на основе иерархии объектов
- критерии поиска
- Sub Критерии
- Значение
- Государство
Я смог получить первый каскад (но не другие из-за проблем с привязкой данных), используя код из следующих ссылка:
http://blogs.msdn.com/b/thebeebs/archive/2011/12/01/price-calculator.aspx
Данные для этих выпадающие возвращается к моей бритвы ViewPage как IEnumrable из SearchCriterion с видом MVC, используя переменную ViewBag.CriteriaData. Код для моих классов выглядит следующим образом:
public class SearchCriterion
{
public string Text { get; set; }
public string Value { get; set; }
public List<SubCriterion> SubCriteria { get; set; }
}
public class SubCriterion
{
public string SearchCriterionValue { get; set; }
public string Text { get; set; }
public string Value { get; set; }
public List<ColumnValue> ColumnValues { get; set; }
}
public class ColumnValue
{
public string SearchCriterionValue { get; set; }
public string SubCriterionValue { get; set; }
public string Text { get; set; }
public string Value { get; set; }
public IEnumerable<StateValue> StateValues { get; set; }
}
public class StateValue
{
public string SearchCriterionValue { get; set; }
public string SubCriterionValue { get; set; }
public string ColumnValue { get; set; }
public IEnumerable<int> InputStateIds { get; set; }
public IEnumerable<int> OutputStateIds { get; set; }
public int SelectedInputStateId { get; set; }
public int SelectedOutputStateId { get; set; }
public string Text { get; set; }
public string Value { get; set; }
}
Вопросы, я столкнулся в следующих частях кода .cshtml:
Что я указываю в этом шаблоне для двух других выпадающие. например третий выпадающий должен быть связан с ColumnValue.Value (ColumnValue является частью SubCriterion)
<script id='criteriaRowTemplate' type='text/html'> <tr> <td><select data-bind='options: criteriaData, optionsText: "Text", optionsCaption: "Search Criterion", value: SearchCriterion' /></td> <td><select data-bind='visible: SearchCriterion, options: SearchCriterion() ? SearchCriterion().SubCriteria : null, optionsText: "Text", optionsCaption: "Sub Criterion", value: SubCriterion' /></td> <td><select data-bind='visible: SubCriterion, options: SubCriterion() ? SubCriterion().ColumnValues : null, optionsText: "Text", optionsCaption: "Column Value", value: ColumnValue'/></td> <td><select data-bind='visible: ColumnValue, options: ColumnValue() ? ColumnValue().StateValues : null, optionsText: "Text", optionsCaption: "State", value: StateValue'/></td> <td><button data-bind='click: function() { viewModel.removeLine($data) }'>Remove</button></td> </tr> </script>
Правильно ли это?
var CriteriaLine = function() { this.SearchCriterion = ko.observable(); this.SubCriterion = ko.observable(); this.ColumnValue = ko.observable(); this.StateValue = ko.observable(); // Whenever the Search Criteria changes, reset the Sub Criteria selection this.SearchCriterion.subscribe(function() { this.SubCriterion(undefined); }.bind(this)); this.SubCriterion.subscribe(function() { this.ColumnValue(undefined); }.bind(this)); this.ColumnValue.subscribe(function() { this.StateValue(undefined); }.bind(this));
};
Как сопоставить полный объект C# с объектом Javascript? Это работает, если мы просто первые два выпадающие:
// Create a Javascript object object with the same property names as the C# object var dataToSearch = $.map(this.lines(), function (line) { return line.StateValue() ? line.StateValue() : undefined; }); var SearchObject = new function() { this.StateValues = dataToSearch; }; // Convert the object to JSON var searchCriteria = JSON.stringify(SearchObject);
нужно ли что-то изменить здесь для связывания?
// Apply the data from the server to the variable var criteriaData = @Html.Raw(@Json.Encode(ViewBag.CriteriaData)); var viewModel = new Criteria(); ko.applyBindings(viewModel, document.getElementById("criteriaDiv"));
EDIT:
Я теперь в состоянии заполнить каскадные выпадающие (обновленный код выше). Теперь у меня есть 4 столбца, каждый столбец имеет одно из выпадающих меню. У меня также есть 1 ... n количество строк, добавляемых динамически с помощью Knockoutjs. Таким образом, пользователь может теперь выбирать значения из этих выпадающих списков и добавлять больше строк выпадающих списков, если захочет. Остается только вернуть значения, которые пользователь выбирает для выпадающих списков контроллера (пункт 3 выше). Я не знаю, как это сделать. Любая помощь будет оценена по достоинству.
EDIT 2:
Добавлен рабочий код для товара # 3 и модифицировал классы ColumnValue и StateValue.
Ваша реализация выглядит пугающей, так как у вас есть 4 отдельных раскрывающихся списка, где каждая подпапка вниз зависит от значения родительского элемента (то есть подкритерий зависит от значения критериев). Итак, допустим, у вас есть 10 разных критериев, и по каждому критерию они могут иметь 10 подкатегорий и каждый из этих 10 значений и каждый из этих 10 столбцов. Это 10 + 10^2 + 10^3 + 10^4 значения или возможные 11 110 комбинаций. Вместо этого вам следует избавиться от коллекций List <>, и каждый из них выдает запрос AJAX для заполнения дочернего элемента. – Makotosan
Я бы тоже испугался, если бы у меня было так много случаев. Но выходы здесь не просто зависят от родителя, они также зависят от их дедушки и бабушки. Таким образом, общее количество вариантов довольно ограничено. В раскрывающемся списке критериев поиска будет только 6 значений, под критерии 2-4 значения при макс, выпадающее значение будет иметь в основном 2-3 значения, но в некоторых случаях может иметь около 10 значений, а в последнем выпадающем списке будет всего 2 значения. Я передаю все это обратно как вложенный объект, основанный на моем кеше, без каких-либо отставаний в производительности. Поэтому я не против отправки всех данных, если seomeone может помочь мне с синтаксисом привязки. – Yasir
ОК, поэтому из того, что я могу сказать, вы правильно разбиваете данные C# на объект JavaScript. Я использую $ .json.decode (someObject) (аддон jQuery), но это то же самое. Что касается подписок и изменений данных, я бы пошел с чем-то вроде предложенного ниже, где вы действительно привязаны к вычисленным значениям. Затем вы можете упростить ViewModel, а не пытаться самостоятельно отслеживать все. – farina