我在同一个项目中同时使用Knockout(版本2.0)和jQuery Mobile(版本1.0.1)。问题在于将数据绑定到选择列表。 jQuery Mobile以一种看似选择的值和实际列表是单独元素的方式呈现选择列表。这是通过执行
来解决的$(element).selectmenu('refresh', true);
更改列表或选定值后。根据我的经验,这是一个危险的情况,因为开发人员经常忘记刷新选择列表。
为了简化这一点,我编写了自己的Knockout绑定处理程序。这些值使用以下代码绑定到选择列表:
<select name="selection" data-bind="jqmOptions: values, optionsValue: 'id', optionsText: 'name', value: selectedValue">
</select>
jqmOptions的实现:
ko.bindingHandlers.jqmOptions = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.options.init !== 'undefined') {
ko.bindingHandlers.options.init(element, valueAccessor, allBindingsAccessor, viewModel);
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.options.update !== 'undefined') {
ko.bindingHandlers.options.update(element, valueAccessor, allBindingsAccessor, viewModel);
}
var instance = $.data(element, 'selectmenu');
if (instance) {
$(element).selectmenu('refresh', true);
}
}
};
这使用本机options
绑定,但除此之外,它会在更改列表值后自动刷新选择列表。但是当我更改所选值时,这有问题。如果我首先设置列表值,我的jqmOptions将刷新选择列表,但此时,尚未设置所选值。我最终得到一个选择列表,它具有所有正确的值,并在内部选择了正确的选项,但jQuery Mobile仍然显示默认值为选中。
this.values(someArrayOfValues);
this.selectedValue(oneOfTheArrayValues);
Knockout不允许我先设置所选值然后设置列表值,因为在这种情况下,当我设置所选值时没有允许的值。因此,所选值始终未定义。
有没有办法编写一个Knockout自定义绑定,在两种情况下都会刷新选择列表元素:更改列表值和更改选定值时?
目前我使用以下代码解决了这种情况:
this.values(someArrayOfValues);
this.selectedValue(oneOfTheArrayValues);
this.values(someArrayOfValues);
然而,这不是一个非常优雅的解决方案,我想更好地解决它。
答案 0 :(得分:14)
我最终解决了自己。我写了自己的jqmValue绑定:
ko.bindingHandlers.jqmValue = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.value.init !== 'undefined') {
ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, viewModel);
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.value.update !== 'undefined') {
ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor, viewModel);
}
var instance = $.data(element, 'selectmenu');
if (instance) {
$(element).selectmenu('refresh', true);
}
}
};
然后将选择列表代码更改为以下内容:
我在问这个问题之前已经尝试过这个问题了,但显然我写得很差,因为它不起作用。然而,现在有了一双新鲜的眼睛,我设法正确实现它,所以希望这个答案也解决了其他Knockout和jQuery Mobile用户的问题。
答案 1 :(得分:4)
根据我的个人经验(使用jquerymobile 1.1.0和knockoutjs 2.1.0),我只使用 jqmoptions (如第一篇文章中所见)绑定,以便有效地敲除绑定到a选择。要使'value'绑定与select配合使用,只需在绑定中将其声明为
<select name="myname" id="myid" data-bind="value: myvalue, jqmoptions: myvalues, optionsValue: 'id', optionsText: 'desc'"></select>
查看订单是强制性的:http://goo.gl/nVbHc
答案 2 :(得分:1)
为了清楚起见,现在KO 3.x的最佳解决方案是:
ko.bindingHandlers.jqmValue = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
if (typeof ko.bindingHandlers.value.init !== 'undefined') {
ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor, viewModel);
}
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var instance;
if (typeof ko.bindingHandlers.value.update !== 'undefined') {
ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor, viewModel);
}
instance = $.data(element, 'mobile-selectmenu');
if (instance) {
$(element).selectmenu('refresh', true);
}
}
};
匹配的HTML使用:
<select data-bind="options: optionsList, optionsValue: 'Id', optionsText: 'Title', jqmValue: knockoutobservable"></select>
答案 3 :(得分:0)
同时使用Knockout 3.3 + jQuery Mobile 1.4.5也有同样的问题 当我有多个选择绑定一个值
<select id="myselect1" data-bind="options: modelsA-Z, value: myModel"></select>
<select id="myselect2" data-bind="options: modelsFamous, value: myModel"></select>
第1 /第2选择未显示初始值,第2次未更新后...... 我最后使用下面的绑定:(替换上面的值:myModel - &gt; jqmValue:myModel)
ko.bindingHandlers.jqmValue = {
init: function (element, valueAccessor) {
var result = ko.bindingHandlers.value.init.apply(this, arguments);
try {
$(element).selectmenu("refresh");
} catch (x) {}
return result;
},
update: function (element, valueAccessor) {
ko.bindingHandlers.value.update.apply(this, arguments);
var value = valueAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
try {
$(element).selectmenu("refresh");
} catch (x) {}
}
};