请查看此jsfiddle
我遇到两个问题:
- 我无法返回所选对象的(cascadingOption)文本
- 我不知道如何忠实地将下拉列表翻译为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…
- 创建一个可观察对象来存储Id
- 更改您的值绑定以使用Id observable
- 添加optionsValue绑定以从源选项返回唯一Id。这将用于同步select2选项和select选择
- 向可观察Id添加订阅以筛选选项并从选项数组返回对象
- 向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/
希望能有所帮助。