Knockout 和 jQuery Mobile:将数据绑定到选择列表
我在同一个项目中同时使用 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);
但这不是非常优雅的解决方案,我想更好地解决它。
I'm using both Knockout (version 2.0) and jQuery Mobile (version 1.0.1) in the same project. The problem is with binding data to select lists. jQuery Mobile presents select lists in a way where the seemingly selected value and the actual list are separate elements. This is fixed by executing
$(element).selectmenu('refresh', true);
after changing either the list or the selected value. Based on my experience, this is a dangerous situation as developers often forget to refresh select list.
To ease this, I wrote my own Knockout binding handler. The values are bound to the select list with following code:
<select name="selection" data-bind="jqmOptions: values, optionsValue: 'id', optionsText: 'name', value: selectedValue">
</select>
The implementation of 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);
}
}
};
This uses the native options
binding but in addition to that, it automatically refreshes select lists after changing the list values. There is a problem with this however when I'm changing the selected value. If I first set the list values, my jqmOptions refreshes the select list but at that point, the selected value is not yet set. I end up with a select list, which has all the correct values and internally the right option is selected, but jQuery Mobile still displays the default value as selected.
this.values(someArrayOfValues);
this.selectedValue(oneOfTheArrayValues);
Knockout doesn't allow me to first set the selected value and then setting the list values, because in this case there are no allowed values when I'm setting the selected value. Thus the selected value is always undefined.
Is there a way to write a Knockout custom binding which would refresh the select list element in both cases: when changing the list value and when changing the selected value?
Currently I solve this situation with following code:
this.values(someArrayOfValues);
this.selectedValue(oneOfTheArrayValues);
this.values(someArrayOfValues);
This is not very elegant solution however and I would like to solve it better.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我最终解决了自己。我编写了自己的 jqmValue 绑定:
然后将选择列表代码更改为以下内容:
我昨天在问问题之前已经尝试过实现这个,但显然我当时写得很差,因为它不起作用。然而,现在我以全新的眼光成功地正确实现了它,所以希望这个答案也能解决其他 Knockout 和 jQuery Mobile 用户的问题。
I ended up solving myself. I wrote my own jqmValue binding:
The select list code is then changed to following:
I already tried implementing this yesterday before asking the question, but apparently I wrote it poorly then because it didn't work. However, now with a fresh pair of eyes I managed to implement it correctly so hopefully this answer solves the problem for other Knockout and jQuery Mobile users too.
就我个人的经验(使用 jquerymobile 1.1.0 和 knockoutjs 2.1.0)而言,我仅使用 jqmoptions (如第一篇文章中所示)绑定来将有效的淘汰赛绑定到选择。要使“值”绑定与 select 一起使用,只需在绑定中将其声明为第一个即可。
看起来顺序是强制性的:http://goo.gl/nVbHc
For my personal experience (with jquerymobile 1.1.0 and knockoutjs 2.1.0), I've only used jqmoptions (as seen in the first post) binding to have a valid knockout binding to a select. To make 'value' binding works with select, simply declare it as first in the binding
Looks that the order is mandatory: http://goo.gl/nVbHc
为了清楚起见,现在 KO 3.x 的最佳解决方案是:
以及匹配的 HTML 使用:
Just for clarity, the best solution now for KO 3.x would be:
And the matching HTML use:
同时使用 Knockout 3.3 + jQuery Mobile 1.4.5 也遇到了同样的问题
当我有多个选择绑定一个值时,
第一个/第二个选择未显示初始值,第二个选择后未更新...
我最终使用下面的绑定:(替换上面的 value:myModel -> jqmValue: myModel)
using both Knockout 3.3 + jQuery Mobile 1.4.5 and also had the same problem
when i had multiple selections which binding one value
1st/2nd select not shown the init value and 2nd not updated after...
I finally use below binding: (replace above value:myModel -> jqmValue: myModel)