2014-02-19 6 views
0

Пожалуйста, смотрите этот jsfiddleКаскадные выпадающие с knockout.js и выбор2

Я встречая два вопроса:

  1. я неспособен вернуть (cascadingOption) текст выбранного объекта.
  2. Я проиграл, как верно перевести выпадающие списки на select2.

В частности, это:

<select id="make" data-bind="options: carMakers, 
           value: selectedMake, 
           optionsText : 'text', 
           optionsCaption : 'Select your make'"> 
    </select><br/> 
    Selected Make: <span data-bind="text: selectedMake"></span><br/> 

возвращает [объект Object] на экране. Если я изменю последнюю строку до span data-bind="text: selectedMake.text", она ничего не вернет. Однако, если я использую subscribe от нокаута и войдите в консоль, я могу вернуть object.text в порядке?

Вторая проблема заключается в том, что я изменяю первый тег select, добавляя select2: { } к своему атрибуту привязки данных. Это правильно изменит выпадающий список на стиль select2, но все каскадные свойства разваливаются.

Любая помощь или руководство будет принята с благодарностью.

ответ

2

selectedMake является наблюдаемым, его значение будет каскадным экземпляром Option. Для того, чтобы использовать это в пролете: текст привязки вам потребуется:

<span data-bind="text: selectedMake().text"></span> 

Это работает, когда вы используете подписку, потому что вы получаете значение наблюдаемой.


Select2 пытается синхронизировать элемент выбора с его внутренним состоянием. К сожалению, он зависит от каждой опции, имеющей значение Id. Поскольку вы не используете привязки optionsValue, это не сработает. Я также использую select2, но я изменил их код, чтобы использовать optionIndex вместо Id и довольно сложную привязку select2 для управления различиями, например Ajax и multiselect.

Однако, вы получите ваш образец работы с выбор2 ...

  1. Создать наблюдаемым для хранения Id.
  2. Изменить привязку значения, чтобы использовать идентификатор, наблюдаемый
  3. Добавить опцииСвязь привязки для возврата уникального идентификатора из исходной опции. Это будет использоваться для синхронизации опции select2 и выберите опцию.
  4. Добавить подписку на Ид наблюдаемого для фильтрации параметров и возвращают объект из параметров массива
  5. Добавить подписку на значение наблюдаемого, чтобы сохранить Id в синхронизации (быть осторожным бесконечным цикл между 2 подписками)

Я обновил ваш JSFiddle, но отличия ниже. В этом случае я создаю функцию-обертку для создания пары наблюдаемых/идентификаторов с подписками между 2. . Связывание выбора имеет другое значение привязки значения и добавленную привязку привязки к объекту Связывание диапазона имеет другое значение привязки текста.

HTML

<div> 
    <select id="make" data-bind="options: carMakers, value: selectedMake.id, optionsValue: 'text', optionsText : 'text', optionsCaption : 'Select your make', select2: {}"></select><br/> 
    Selected Make: <span data-bind="text: selectedMake().text"></span><br/> 
    <select id="type" data-bind="options: carTypes, value: selectedType.id, optionsValue: 'text', optionsText : 'text', optionsCaption : 'Select your type', enable : carTypes, select2: {}"></select><br/> 
    Selected Model: <span data-bind="text: selectedType().text"></span><br/> 
    <select id="model" data-bind="options: carModels, value: selectedModel.id, optionsValue: 'text', optionsText : 'text', optionsCaption : 'Select your Model', enable: carModels, select2: {}"></select><br/> 
    Selected Model: <span data-bind="text: selectedModel().text"></span><br/> 
</div> 

Javascript

var makeObservableForSelect2 = function(sourceOptions, idSelector) { 
    var target = ko.observable({}); 
    target.id = ko.observable(); 

    target.id.subscribe(function(id) { 
     var realSource = ko.unwrap(sourceOptions) 
     if (!realSource) { 
      return; 
     }; 
     // Don't set target if id already matches to stop infinite loop. 
     if (target() && target()[idSelector] === id) { 
      return; 
     } 

     target(realSource.filter(function(item) { return item[idSelector] === id; })[0] || {}); 
    }); 

    target.subscribe(function(value) { 
     // Don't set id if id already matches to stop infinite loop. 
     if (target.id() && value[idSelector] === target.id()) { 
      return; 
     } 

     target.id(value[idSelector]); 
    }); 

    return target; 
}; 

var viewModel = { 
    carMakers: buildData() 
}; 

viewModel.selectedMake = makeObservableForSelect2(viewModel.carMakers, 'text'); 

viewModel.carTypes = ko.computed(function(){ 
    return viewModel.selectedMake() ? viewModel.selectedMake().childOptions : null; 
}); 

viewModel.selectedType = makeObservableForSelect2(viewModel.carTypes, 'text'); 

viewModel.carModels = ko.computed(function(){ 
    return viewModel.selectedType() ? viewModel.selectedType().childOptions : null; 
}); 

viewModel.selectedModel = makeObservableForSelect2(viewModel.carModels, 'text'); 
2

Работа скрипку: http://jsfiddle.net/jiggle/Lw2qJ/

Выпуск 1:

Вы могли бы сделать span data-bind="text: selectedMake().text" (обратите внимание на скобки), но только если selectedMake всегда будет иметь значение (и, следовательно, имеет свойство .text).

Есть несколько других способов сделать это, которые изложены на http://www.knockmeout.net/2011/08/simplifying-and-cleaning-up-views-in.html

Выпуск 2:

Однако, когда я начал смотреть на выпуск 2, я обнаружил, что свойство optionsValue должен быть установлен select2 будет работать правильно (хотя кто-то может исправить меня по этому поводу), поэтому я немного переработал так, чтобы ваш selectedMake больше не являлся объектом, а скорее текстовым свойством и параметрамиValue: «text» следующим образом:

<select id="make" data-bind="select2:{} , options: carMakers, value: selectedMake, 
optionsValue:'text', 
optionsText : 'text', optionsCaption : 'Select your make'"></select><br/> 

Это означало для каскадных computeds на следующие уровни, вы должны изменить его на первый взгляд вверх сделайте из выбранного текстового значения марки, как это:

viewModel.carTypes = ko.computed(function(){ 
if(viewModel.selectedMake()){ 
    var make = ko.utils.arrayFirst(viewModel.carMakers,function(item){ 
     console.log(item.text,viewModel.selectedMake()); 
      return item.text===viewModel.selectedMake();   
    }); 
    return make.childOptions; 
} 
}); 

Это также означает, что вы можете просто использовать Selected Make: <span data-bind="text: selectedMake"></span> довольно чем использовать скобки, поскольку вы не пытаетесь получить доступ к свойству наблюдаемого.

Вот скрипка снова: http://jsfiddle.net/jiggle/Lw2qJ/

Надеется, что это помогает.

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

  • Нет связанных вопросов^_^