【问题标题】:Knockout and jQuery Mobile: Binding data to select listsKnockout 和 jQuery Mobile:将数据绑定到选择列表
【发布时间】:2012-02-21 07:56:28
【问题描述】:

我在同一个项目中同时使用了 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);

然而,这不是很优雅的解决方案,我想更好地解决它。

【问题讨论】:

    标签: jquery-mobile knockout.js


    【解决方案1】:

    我最终解决了自己。我写了自己的 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 用户的问题。

    【讨论】:

    • 在找到你的问答之前,我一直在努力。感谢分享
    • 您是否为淘汰赛 3 更新了此内容?现在这似乎对我不起作用
    • 对于 KO 3,您需要将一行更新为 var instance = $.data(element, 'mobile-selectmenu');
    • 还要确保 jqmValue 绑定在元素绑定列表中的 options 绑定之后,否则它可能无法正确更新初始值
    【解决方案2】:

    根据我的个人经验(使用 jquerymobile 1.1.0 和 knockoutjs 2.1.0),我只使用了 jqmoptions(如第一篇文章中所示)绑定来将有效的淘汰绑定绑定到选择。要使“值”绑定与 select 一起使用,只需在绑定中将其声明为 first

    <select name="myname" id="myid" data-bind="value: myvalue, jqmoptions: myvalues, optionsValue: 'id', optionsText: 'desc'"></select>
    

    看来订单是强制性的:http://goo.gl/nVbHc

    【讨论】:

    【解决方案3】:

    为了清楚起见,现在 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>
    

    【讨论】:

      【解决方案4】:

      同时使用 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>
      

      第一次/第二次选择未显示初始值,第二次未更新后... 我终于使用下面的绑定:(替换上面的值:myModel -> 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) {}
          }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-16
        • 2013-02-15
        • 2012-04-08
        • 1970-01-01
        • 2014-07-29
        • 2013-01-08
        • 2015-01-19
        • 2013-01-16
        相关资源
        最近更新 更多