为什么我的BootstrapSwitch无法在使用foreach构建的挖空表中工作

时间:2013-09-16 10:26:41

标签: javascript twitter-bootstrap knockout.js

我正在尝试用这个好看的bootstrap switch替换表格中的复选框。

我也使用了敲除和绑定处理程序,如link所示。

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

我已在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);

2 个答案:

答案 0 :(得分:2)

你使用的是较旧版本的bootstrapSwitch(1.3),它会自动在带有'.switch'类的元素上执行插件,给人的印象就是使用了自定义绑定。

我已将插件更新到最新版本,并在init绑定方法中启动插件,例如:

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
    }
}

升级最新版本的插件似乎可以解决问题:http://jsfiddle.net/badsyntax/59wnW/5/

[更新] - 我认为问题的根本原因是插件在DOM就绪时启动自身,以及在构建DOM之间进行淘汰。

此示例适用于旧版本的bootstrapSwitch,只要您在绑定视图模型后启动插件http://jsfiddle.net/badsyntax/59wnW/6/

答案 1 :(得分:2)

这是BootstrapSwitch(http://www.bootstrap-switch.org/)v3.2.1的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);
    }
  }
};