【问题标题】:Knockout 3+ How do you bind a jquery mobile radio button to knockout?Knockout 3+ 如何将jquery mobile 单选按钮绑定到knockout?
【发布时间】:2017-05-02 04:29:15
【问题描述】:

https://jsfiddle.net/9L8r9etf/2/

我一直在尝试几种不同的方法,但这是我得到的最接近的方法。出于某种原因 this.checked 总是正确的。

javascript:

ko.bindingHandlers.jqmChecked = {
    init: function (element, valueAccessor) {
        ko.utils.unwrapObservable(valueAccessor()); // This hack for knockout v3
        // set the dom element to a checkbox and initialize it (for jquerymobile)
        var checkbox = $(element);
        // let jquerymobile enhance the element
        checkbox.removeAttr('data-role');
        // make it so
        checkbox.checkboxradio();
        //register change event to update the model on changes to the dom
        checkbox.on('change', function (e) {
                if(this.checked)
            valueAccessor()(this.value);
        });
    },
    update: function (element, valueAccessor) {
        // update the checked binding, important for correct radio button behaviour.
        //ko.bindingHandlers.checked.update(element, valueAccessor);
        //ko.utils.unwrapObservable(valueAccessor()); // This hack for knockout v3

        // and refresh the element (for jquerymobile)
        var checkbox = $(element);
        checkbox.checkboxradio('refresh');
        checkbox.prop("checked", valueAccessor()()).checkboxradio("refresh");

    }
};

var ViewModel = function(repeat) {
        var self = this;
        self.testa = ko.observable(true);
    self.test = ko.observable("dyn");
    if(repeat){
    self.subView = ko.observable(new ViewModel(false));
    }
};

ko.applyBindings(new ViewModel(true));

html:

<fieldset data-role="controlgroup" data-mini="true" data-type="horizontal">
  <label><input type="radio" value="inp" name="inpdynout2" checked data-bind="jqmChecked:test"/> inp</label>
  <label><input type="radio" value="dyn" name="inpdynout2" data-bind="jqmChecked:test" /> dyn</label>
  <label><input type="radio" value="out" name="inpdynout2" data-bind="jqmChecked:test" /> out</label>
</fieldset>
<hr/>
x <span data-bind="text:test"></span><br/>

我知道在淘汰赛 3 中,您需要创建自己的事件侦听器而不是使用 checked.update,但我无法弄清楚如何将它与原始的检查绑定一起使用。

我希望绑定尽可能像淘汰赛 3 香草绑定一样,因为我们已经被自定义绑定不完整的错误所困扰。

【问题讨论】:

    标签: jquery-mobile knockout.js knockout-3.0


    【解决方案1】:

    如果您能分享一些有关您在问题中提到的错误的详细信息,那就太好了。无论如何,为了保持检查的 attr 同步,我会使用这样的东西:

    ko.bindingHandlers.jqmRadio = {
      init: function(element, valueAccessor, allBindings) {
        var value = valueAccessor(),
          valueUnwrapped = ko.unwrap(value);
        if (!valueUnwrapped) {
          var checkedValue = $('input[name=' + element.name + ']:checked').val();
          value(checkedValue);
        }
        return ko.bindingHandlers.checked.init.apply(this, arguments);
      },
      update: function(element, valueAccessor, allBindings) {
        var valueUnwrapped = ko.unwrap(valueAccessor()); // for dependency
        if (!!$.data(element, "mobile-checkboxradio")) {
          (element.value !== valueUnwrapped) ? $(element).removeAttr("checked"): $(element).attr("checked", "checked");
          $(element).checkboxradio("refresh");
        }
      }
    };
    
    var ViewModel = function() {
      var self = this;
      self.test = ko.observable(); // initialized by attr
      self.test2 = ko.observable("dyn"); // initialized by ko
    };
    
    $(document).ready(function() {
      ko.options.deferUpdates = true;
      ko.applyBindings(new ViewModel());
    });
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
      <link rel="stylesheet" href="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.css">
      <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
      <script src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    </head>
    
    <body>
      <div data-role="page">
        <div role="main" class="ui-content">
          <fieldset data-role="controlgroup" data-mini="true" data-type="horizontal">
            <label>
              <input type="radio" name="inpdynout" checked data-bind="checkedValue:'inp', jqmRadio:test"> inp</label>
            <label>
              <input type="radio" name="inpdynout" data-bind="checkedValue:'dyn', jqmRadio:test"> dyn</label>
            <label>
              <input type="radio" name="inpdynout" data-bind="checkedValue:'out', jqmRadio:test"> out</label>
          </fieldset>
          <hr/>
          <br/>
          <fieldset data-role="controlgroup" data-mini="true" data-type="horizontal">
            <label>
              <input type="radio" name="inpdynout2" data-bind="checkedValue:'inp', jqmRadio:test2"> inp</label>
            <label>
              <input type="radio" name="inpdynout2" data-bind="checkedValue:'dyn', jqmRadio:test2"> dyn</label>
            <label>
              <input type="radio" name="inpdynout2" data-bind="checkedValue:'out', jqmRadio:test2"> out</label>
          </fieldset>
          <hr/>
          <pre data-bind="text:ko.toJSON($data)"></pre>
        </div>
    
      </div>
    </body>
    
    </html>

    【讨论】:

    • 使用 deferUpdates 和不使用有什么区别?这不会影响我的应用程序中的其他内容吗? (我们还没有提供可用的版本)你能评论一下 $.data(element, "mobile-checkboxradio") 的用途吗?和 $(element).attr("checked", "checked"); vs $(element).prop("checked", element.value === unwrapped)
    • 问题中提到的错误主要是其他人编写的不相关的自定义绑定的内部问题。人们在文档中说他们适用于复选框/单选按钮,但最终只适用于复选框等。要么由于缺乏测试或版本之间的语义变化。
    • @RyanTheLeach:1)延迟更新;我只是针对失败进行了测试,如果您不使用它,只需省略该行。 2) $.data(element, "mobile-checkboxradio" 是为了测试 JQM 是否已经创建了小部件,以避免错误 "checkboxradio is not an instance"。3) 已检查:您可能已经在示例代码中使用了它您获取表单数据并提交/存储表单数据,因此通过使用 attr 表单数据将匹配 ko checkedValue 绑定(不是使用 prop 或什么都不使用的情况 - 检查检查元素)。
    • @RyanTheLeach:可悲的是,广受好评的淘汰赛向后兼容性已经从 ko v2.x 到 3.x 被打破,因为它要求在标记中更改已检查的绑定与 checkedValue,我对此也很不满意决定。
    【解决方案2】:
    ko.bindingHandlers.jqmCheckedRadio = {
        init: function (element, valueAccessor) {
            // set the dom element to a checkbox and initialize it (for jquerymobile)
            var checkbox = $(element);
            // let jquerymobile enhance the element
            checkbox.removeAttr('data-role');
            // make it so
            checkbox.checkboxradio();
    
            checkbox.on('change', function (e) {
                if ($(this).prop( "checked")) {//this is returning true always.
                    valueAccessor()(this.value);
                }
            });
        },
        update: function (element, valueAccessor) {
            // update the checked binding, i.e., check or uncheck the checkbox
            var unwrapped = ko.utils.unwrapObservable(valueAccessor()); 
            // and refresh the element (for jquerymobile)
            $(element).prop("checked", element.value === unwrapped).checkboxradio("refresh");
        }
    };
    

    这遵循了多个单选按钮绑定到单个 observable 的淘汰 3 语义,但使用它们的属性值而不是 checkValue。

    尚未针对复选框或布尔单选按钮进行测试。

    如果您需要动态数量的单选按钮,它也应该可以正常工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-25
      • 2013-05-01
      • 1970-01-01
      • 2013-10-27
      • 1970-01-01
      • 2012-04-20
      • 2015-01-19
      • 2013-01-08
      相关资源
      最近更新 更多