我正在评估select2 v4.0与我们从v3.5.x升级有关。我们正在使用淘汰赛v3.5.2。我们的场景是我们希望允许用户根据来自ajax调用的js对象选择多个选项。 selectedoptions绑定应该将整个js对象存储在它所绑定的observablearray中,而不仅仅是id列表。
在我的测试中,这是我发现的
这是一个带有预定义选项列表的select2。每个选项都有id,text和displayText属性。结果是multipleSelectedObjects可观察数组最终有一个整个js对象的数组,这是我所期望的基于我没有设置optionsValue参数的事实
<select class="multipleSelect" data-bind="options: multipleOptions, selectedOptions: multipleSelectedObjects, optionsText: 'displayText', select2v4: multipleOptionsSetup" style="width: 200px">
这是一个带有预定义选项列表的select2。每个选项都有id,text和displayText属性。结果是multipleSelectedValue可观察数组最终有一个int数组,表示所选js对象的id,这是我所期望的基于我设置optionsValue参数的事实
<select class="multipleSelect3" data-bind="options: multipleOptions, selectedOptions: multipleSelectedValue, optionsText: 'text', optionsValue: 'id', select2v4: multipleOptionsSetup" style="width: 200px">
这是一个使用ajax选项进行服务调用以返回选项的select2。返回的每个选项都有id,text和displayText属性。结果是selectedItems可观察数组最终有一个int数组,表示所选js对象的id。这不是我所期望的。我试着像上面第一个select2一样设置optionsText属性,但这并没有什么区别
<select id="select2Input" data-bind="selectedOptions: selectedItems, select2v4: selectSetup" style="width: 400px">
我认为这可能是一个select2问题,但我不确定。我们的select2v4绑定处理程序如下所示。在最后一个场景中,当knockout命中selectedOptions部分时,该值是一个字符串,这使我认为select2在使用ajax时没有设置为传递整个对象。还有其他人经历过吗?这是一个错误还是设计?
// NOTE: this binding handler is made for select2 version 4.0
ko.bindingHandlers.select2v4 = {
init: function (element, valueAccessor, allBindingsAccessor) {
var bindingValue = ko.unwrap(valueAccessor());
var allBindings = allBindingsAccessor();
var valueDataChange;
// Observe external data changes; set data on change
if (ko.isObservable(allBindings.valueData)) { // special data binding
var onChange = false;
allBindings.valueData.subscribe(function (value) { // subscribe to external data changes
if (onChange) return; // ignore if on change to prevent recursion
$(element).select2("data", value, false); // set data explicitly; do not trigger change });
if (ko.isWritableObservable(allBindings.valueData)) {
valueDataChange = function () {
onChange = true; // suppress valueData subscription
allBindings.valueData($(element).select2("data"));
onChange = false;
};
$(element).on("change", valueDataChange); // update observable on data change
}
}
// Observe external value changes
else if (ko.isObservable(allBindings.value)) { // input or single select with observable value binding
allBindings.value.subscribe(function (value) { // subscribe to external value changes
if (typeof value === "string") { // optionsValue or tags specified
if (bindingValue.tags) { // tags specified
value = value.split(bindingValue.separator || ','); // split on value separator
}
$(element).val(value); // set val to allow select2 to resolve data from values; do not trigger change
}
else { // optionsValue not specified, value is complex data
$(element).select2("data", value, false); // set data explicitly; do not trigger change
}
});
}
// Observe external selection changes
else if (ko.isObservable(allBindings.selectedOptions)) { // multiselect with observable selection binding
allBindings.selectedOptions.subscribe(function (value) { // subscribe to external selection changes
if (value.length > 0 && typeof value[0] === "string") { // optionsValue specified
$(element).val(value); // set val to allow select2 to resolve data from values; do not trigger change
}
else { // optionsValue not specified, value is complex data
$(element).select2("data", value, false); // set data explicitly (only works if complex data object has 'id' property); do not trigger change
}
});
}
// Destroy select2 on element disposal
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).select2('destroy');
if (valueDataChange != null) {
$(element).off("change", valueDataChange);
}
});
// Apply select2 and initialize data; delay to allow other binding handlers to run
setTimeout(function () {
// Apply select2
$(element).select2(bindingValue);
// Initialize data
if ("valueData" in allBindings) {
$(element).select2("data", ko.unwrap(allBindings.valueData), false);
}
}, 0);
}
};
答案 0 :(得分:1)
与先前版本相比,select2 v4在内部的工作方式有很多重大变化。其中之一是select2在使用ajax加载数据(aka typeahead)的情况下如何存储所选对象。我的同事能够弄清楚,在这种情况下,所选对象存储在只读集合中,并且在进行更改时不能正确通知,加上正常绑定不能按预期工作。正如我们所发现的,绑定到selectedOptions不会导致对象列表,而是导致id。他想出了下面显示的select2的绑定处理程序,它将处理常规选择样式绑定并添加一个名为selectData的新绑定,如果您使用ajax加载远程数据,它将为您提供所选对象的列表。如果使用ajax加载数据并希望获取所选对象的列表而不是id,则只需要selectData绑定,否则可以绑定到value或selectedOptions,并且设置类型将按预期工作。
var CurrentUser = function() {
return function () {
var profile = {
isLoggedIn: false,
username: "",
token: ""
};
var setProfile = function (username, token) {
profile.username = username;
profile.token = token;
profile.isLoggedIn = true;
return profile;
};
var getProfile = function () {
return profile;
}
return {
setProfile: setProfile,
getProfile: getProfile
}
}};
CurrentUser.$inject = [];
答案 1 :(得分:-1)
您是否尝试过使用optionsAfterRender设置值?
这对我有用:
<select id="selectArticles" multiple
data-bind="options: availableArticles, selectedOptions: selectedArticles,
optionsText: function(item){return item.title},
optionsAfterRender: function(option, item){option.value = item}">
</select>