5

我正在尝试用这个好看的引导开关替换表格中的复选框。

我还使用了此链接建议的敲除和绑定处理程序。

但是,我无法使绑定处理程序正常工作,或者无法在使用每个敲除器构建的表中单击该开关。

我已经在jsfiddle中复制了这个问题。

我仍在学习 javascript 和淘汰赛,只是无法弄清楚绑定处理程序或开关中出了什么问题。

有任何想法吗?

的HTML:

<div>
<input type="checkbox" data-bind="checked: on" />
</div>
<div>
    <span data-bind="text: on() ? 'on' : 'off'"></span>
</div>
<div class="switch switch-large" data-bind="bootstrapSwitchOn: on">
    <input type="checkbox" />
</div>

<p>Why doesn't this work in a table?</p>

<table class="table table-striped table-condensed table-bordered">
    <thead>
    <tr>
        <th>Name</th>
        <th>Old</th>
        <th>Old toggle With CheckBox</th>
        <th>Old toggle With Switch</th>
    </tr>
    </thead>
    <tbody data-bind="foreach: items">
        <tr>
            <td data-bind="text: Name"></td>
            <td data-bind="text: Old"></td>
            <td>
                <input type="checkbox" data-bind="checked: Old" />
            </td>
            <td>
                <div class="switch switch-large" data-bind="bootstrapSwitchOn: Old">
                    <input type="checkbox" />
                </div>
            </td>
        </tr>
    </tbody>
</table>

绑定处理程序和淘汰赛视图

/**
 * Knockout binding handler for bootstrapSwitch indicating the status
 * of the switch (on/off): https://github.com/nostalgiaz/bootstrap-switch
 */
ko.bindingHandlers.bootstrapSwitchOn = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        $elem = $(element);
        $(element).bootstrapSwitch('setState', ko.utils.unwrapObservable(valueAccessor())); // Set intial state
        $elem.on('switch-change', function (e, data) {
            valueAccessor()(data.value);
        }); // Update the model when changed.
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var vStatus = $(element).bootstrapSwitch('status');
        var vmStatus = ko.utils.unwrapObservable(valueAccessor());
        if (vStatus != vmStatus) {
            $(element).bootstrapSwitch('setState', vmStatus);
        }
    }
};

var vm = {
    on: ko.observable(true),

    items: ko.observableArray([
        {Name: "Dave", Old: ko.observable(false)},
        {Name: "Richard", Old: ko.observable(true)},
        {Name: "John", Old: ko.observable(false)}
    ])    
}

ko.applyBindings(vm);
4

2 回答 2

2

You were using an older version of bootstrapSwitch (1.3) which automatically executes the plugin on elements with '.switch' class, giving the impression things were working with the custom binding.

I've updated the plugin to the latest version, and am initiating the plugin within the init binding method, eg:

ko.bindingHandlers.bootstrapSwitchOn = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        $elem = $(element);
        $(element).bootstrapSwitch(); // initiate the plugin before setting options
        $(element).bootstrapSwitch('setState', ko.utils.unwrapObservable(valueAccessor())); // Set intial state
        // .. etc
    }
}

Upgrading the latest version of the plugin appears to fix things: https://jsfiddle.net/badsyntax/59wnW/5/

[UPDATE] - I think the root cause of the issue is a race conditional between the plugin initiating itself on DOM ready, and between knockout building the DOM.

This example works with the old version of bootstrapSwitch, as long as you initiate the plugin after binding the viewmodel: https://jsfiddle.net/badsyntax/59wnW/6/

于 2013-09-16T12:38:41.723 回答
2

这是 BootstrapSwitch v3.2.1 ( http://www.bootstrap-switch.org/ ) 的 Knockout 绑定:

ko.bindingHandlers.bootstrapSwitchOn = {
  init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
    var $elem;
    $elem = $(element);
    $(element).bootstrapSwitch();
    $(element).bootstrapSwitch("state", ko.utils.unwrapObservable(valueAccessor()));
    $elem.on("switchChange.bootstrapSwitch", function(e, data) {
      valueAccessor()(data);
    });
  },
  update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
    var vStatus, vmStatus;
    vStatus = $(element).bootstrapSwitch("state");
    vmStatus = ko.utils.unwrapObservable(valueAccessor());
    if (vStatus !== vmStatus) {
      $(element).bootstrapSwitch("state", vmStatus);
    }
  }
};
于 2014-12-03T16:41:22.920 回答