我编写了一个多选jQuery插件,可以应用于普通的HTML选择元素。
但是,这个插件将解析select元素及其选项,然后从DOM中删除select元素,并插入div和复选框的组合。
我在Knockout中创建了一个自定义绑定处理程序,如下所示:
ko.bindingHandlers.dropdownlist = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
// This will be called when the binding is first applied to an element
// Set up any initial state, event handlers, etc. here
// Retrieve the value accessor
var value = valueAccessor();
// Get the true value of the property
var unwrappedValue = ko.utils.unwrapObservable(value);
// Check if we have specified the value type of the DropDownList items. Defaults to "int"
var ddlValueType = allBindingsAccessor().dropDownListValueType ? allBindingsAccessor().dropDownListValueType : 'int';
// Check if we have specified the INIMultiSelect options otherwise we will use our defaults.
var elementOptions = allBindingsAccessor().iniMultiSelectOptions ? allBindingsAccessor().iniMultiSelectOptions :
{
multiple: false,
onItemSelectedChanged: function (control, item) {
var val = item.value;
if (ddlValueType === "int") {
value(parseInt(val));
}
else if (ddlValueType == "float") {
value(parseFloat(val));
} else {
value(val);
}
}
};
// Retrieve the attr: {} binding
var attribs = allBindingsAccessor().attr;
// Check if we specified the attr binding
if (attribs != null && attribs != undefined) {
// Check if we specified the attr ID binding
if (attribs.hasOwnProperty('id')) {
var id = attribs.id;
$(element).attr('id', id);
}
if (bindingContext.hasOwnProperty('$index')) {
var idx = bindingContext.$index();
$(element).attr('name', 'ddl' + idx);
}
}
if ($(element).attr('id') == undefined || $(element).attr('id') == '') {
var id = "ko_ddl_id_" + (ko.bindingHandlers['dropdownlist'].currentIndex);
$(element).attr('id', id);
}
if ($(element).attr('name') == undefined || $(element).attr('name') == '') {
var name = "ko_ddl_name_" + (ko.bindingHandlers['dropdownlist'].currentIndex);
$(element).attr('name', name);
}
var options = $('option', element);
$.each(options, function (index) {
if ($(this).val() == unwrappedValue) {
$(this).attr('selected', 'selected');
}
});
if (!$(element).hasClass('INIMultiSelect')) {
$(element).addClass('INIMultiSelect');
}
$(element).iniMultiSelect(elementOptions);
ko.bindingHandlers['dropdownlist'].currentIndex++;
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var unwrappedValue = ko.utils.unwrapObservable(valueAccessor());
var id = $(element).attr('id').replace(/\[/gm, '\\[').replace(/\]/gm, '\\]');
var iniMultiSelect = $('#' + id);
if (iniMultiSelect != null) {
iniMultiSelect.SetValue(unwrappedValue, true);
}
}};
ko.bindingHandlers.dropdownlist.currentIndex = 0;
这会将原始HTML select元素转换为我的自定义多选。
然而,当第一次调用update函数时,在init之后,“element”变量仍然是原始的select元素,而不是我的自定义html的包装div。
在页面完全加载并且我更改了我绑定的observable的值之后,根本不会触发更新函数!
不知怎的,我有一种感觉,淘汰不再“知道”该做什么,因为我绑定的原始DOM元素已经消失......
任何想法可能是什么问题?
答案 0 :(得分:0)
Knockout中有清理代码,它会在确定元素不再是文档的一部分时处理用于触发绑定的计算的observable。
您可能会找到隐藏原始元素的方法,或者将绑定放在原始select
的容器上(可能是一个不错的选择),或者重新应用绑定到其中一个新元素
答案 1 :(得分:0)
我今天遇到了类似的问题,这就是我解决它的方法。在我的更新处理程序中,我添加了以下行:
$(element).attr("dummy-attribute", ko.unwrap(valueAccessor()));
这足以防止处理程序被Knockout的垃圾收集器处理掉。
JSFiddle(破碎):http://jsfiddle.net/padfv0u9/
JSFiddle(已修复):http://jsfiddle.net/padfv0u9/2/