请参阅此jsfiddle
我遇到两个问题:
具体来说,这个:
<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吗?
第二个问题是我通过将select2: { }
添加到其数据绑定属性来更改第一个选择标记。这将正确地将下拉列表更改为select2样式,但所有级联属性都会崩溃。
非常感谢任何帮助或指导。
答案 0 :(得分:2)
selectedMake是一个可观察的,它的值将是cascadingOption实例。要在span:text绑定中使用它,您需要:
<span data-bind="text: selectedMake().text"></span>
当你使用subscribe时它会起作用,因为你得到了observable的值。
Select2尝试将select元素与其内部状态同步。不幸的是,它依赖于具有Id值的每个选项。因为您不使用optionsValue绑定,所以这不起作用。我也使用select2但是我已经改变了他们的代码以使用optionIndex而不是Id和一个相当复杂的select2绑定来管理差异,比如Ajax和multiselect。
但是,您的示例使用select2 ...
我已更新了您的JSFiddle,但差异如下。在这里我创建一个包装函数来构建一个observable / id对,其中2之间有订阅。 select绑定具有不同的值绑定值,以及添加的optionValue绑定 span绑定具有不同的文本绑定值。
<强> 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');
答案 1 :(得分: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不再对象,而是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/
希望它有所帮助。