使用knockout.js级联下拉列表,然后选择2



请查看此jsfiddle

我遇到两个问题:

  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 object]返回到屏幕。如果我将最后一行更改为span data-bind="text: selectedMake.text",它将不返回任何内容。但是,如果我使用敲除中的subscribe并登录到控制台,我可以返回object.text fine?

第二个问题是当我通过将select2: { }添加到其数据绑定属性来更改第一个select标记时。这将正确地将下拉列表更改为select2样式,但所有级联属性都会分解。

如有任何帮助或指导,我们将不胜感激。

selectedMake是一个可观察的,它的值将是cascadingOption实例。要在您的span:text绑定中使用此功能,您需要:

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

当你使用subscribe时,它是有效的,因为你得到了可观察的值。


Select2尝试将选择元素与其内部状态同步。不幸的是,它依赖于每个选项都有一个Id值。因为您没有使用optionsValue绑定,所以这将不起作用。我也使用select2,但我已经更改了他们的代码,使用optionIndex而不是Id,并使用相当复杂的select2绑定来管理差异,如Ajax和multiselect。

然而,您的样品使用select2…

  1. 创建一个可观察对象来存储Id
  2. 更改您的值绑定以使用Id observable
  3. 添加optionsValue绑定以从源选项返回唯一Id。这将用于同步select2选项和select选择
  4. 向可观察Id添加订阅以筛选选项并从选项数组返回对象
  5. 向observable值添加订阅以保持Id同步(注意两个订阅之间的无限循环)

我已经更新了您的JSFiddle,但差异如下。在这篇文章中,我创建了一个包装器函数来构建一个可观察的/id对,其中包含2之间的订阅。select绑定具有不同的值绑定值,并添加了optionValue绑定跨度绑定具有不同的文本绑定值。

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');

工作小提琴: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不再是对象,而是text属性和optionsValue:"text",就像这样:

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

这意味着对于下一级的级联计算,你必须将其更改为首先从make的选定文本值中查找make,如下所示:

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/

希望能有所帮助。

最新更新