这不起作用(调用自定义绑定但是下拉列表为空)
<select id="parentArea" class="chosen-select" data-bind="
chosen:{},
options: parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
value: selectedParentArea">
</select>
但这可行(下拉列表已填写)
<select id="parentArea" class="chosen-select" data-bind="
options: parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
value: selectedParentArea">
</select>
我想在下拉列表中添加自定义绑定,但不知道如何操作。
自定义绑定很简单
ko.bindingHandlers.chosen = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
console.log('chosen', element);
$(element).chosen({});
}
};
更新
.chosen({});
是来自另一段Javascript(harvesthq.github.io/chosen)的方法。
我意识到当它被注释掉时,剩余的绑定工作。 我真正需要的是运行“$(element).chosen({});”所有其他装订完成后。
更新2
在应用所有绑定后手动应用“选择”时,它运行良好。例如,我可以使用运行此JS的按钮
function run() {
$('.chosen-select').chosen({});
};
我需要在所有绑定完成后自动执行(回调函数?)。 我不知道怎么做。
更新3
“parentAreas”不是静态数组。它是从Web服务加载的:
function ViewModel() {
var self = this;
self.init = function () {
//load parent areas from web service
};
self.init(); //Running the init code
}
ko.applyBindings( new ViewModel());
我想在父区域准备就绪时初始化“选择”框自定义绑定。
更新4
新版本(有效但不可重用,因为它具有硬编码绑定)
ko.bindingHandlers.chosen = { init:function(element,valueAccessor,allBindingsAccessor,viewModel,context){
viewModel.parentAreas.subscribe(function(newParentAreas) {
if (newParentAreas && newParentAreas.length > 0) {
ko.applyBindingsToNode(element, {
options: viewModel.parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
value: viewModel.selectedParentArea
});
$(element).chosen({});
}
});
}
};
//绑定只是data-bind =“selected:{}
更新5 避免多次初始化(hacky方式)
ko.bindingHandlers.parentAreaComboBox = {
initialised: false,
init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
viewModel.parentAreas.subscribe(function (newParentAreas) {
if (newParentAreas && newParentAreas.length > 0) {
if (ko.bindingHandlers.parentAreaComboBox.initialised) {
return;
}
ko.applyBindingsToNode(element, {
options: viewModel.parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
value: viewModel.selectedParentArea
});
$(element).chosen({});
ko.bindingHandlers.parentAreaComboBox.initialised = true;
}
});
}
};
更新6
我写过通用解决方案(请参阅下面的答案)
答案 0 :(得分:4)
它依赖于绑定顺序的反模式。
如果您有一个自定义绑定需要其他绑定才能在自身之前运行,您应该从自定义绑定中调用这些绑定,如
ko.applyBindingsToNode(element, { options: arr, value: val });
然后执行$(element).chosen
答案 1 :(得分:1)
是的,只需重新排序你的绑定(小提琴:http://jsfiddle.net/gBhbx/4/):
<select id="parentArea" class="chosen-select" data-bind="
options: parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
chosen:{},
value: selectedParentArea">
</select>
答案 2 :(得分:1)
我认为您的问题出在chosen
插件本身。当您在.chosen
标记上应用select
时,它会更改其标记(它不再是正常的html select
)。
所以在你绑定你的应用chosen
自定义绑定然后更改html标记,所以你的绑定不能正常工作..
要解决这个问题,您需要首先应用自定义绑定最后 ..以便正常应用ko绑定,然后应用自定义绑定并更改您的选择(但现在您已经构建了你的选择正确)
更新
在生成option
元素后运行函数,您可以使用optionsAfterRender
回调。查看文档here
另一个脏解决方案是使用settimeout
答案 3 :(得分:1)
通用解决方案
HTML
<select id="parentArea" data-bind="comboBox:{
options: parentAreas,
optionsCaption:'Choose...' ,
optionsText: 'Label',
value: selectedParentArea
}"></select>
和javascript是
ko.bindingHandlers.comboBox = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
var bindings = valueAccessor();
var optionsObservableArray = bindings.options;
optionsObservableArray.subscribe(function (newObservableArray) {
if (newObservableArray && newObservableArray.length > 0) {
if (element.comboBoxInitialised) {
return;
}
ko.applyBindingsToNode(element, {
options: bindings.options,
optionsCaption: bindings.optionsCaption,
optionsText: bindings.optionsText,
value: bindings.value
});
$(element).chosen({});
element.comboBoxInitialised = true;
}
});
}
};