Javascript 淘汰赛+;引导3单选按钮

Javascript 淘汰赛+;引导3单选按钮,javascript,html,twitter-bootstrap,knockout.js,twitter-bootstrap-3,Javascript,Html,Twitter Bootstrap,Knockout.js,Twitter Bootstrap 3,有关: HTML: <div class="btn-group" data-toggle="buttons"> <label class="btn btn-primary"> <input type="radio" name="options" id="option1" value="1" data-bind="checked: optionsValue"> Option 1 </label> <lab

有关:

HTML:

<div class="btn-group" data-toggle="buttons">
    <label class="btn btn-primary">
        <input type="radio" name="options" id="option1" value="1" data-bind="checked: optionsValue"> Option 1
    </label>
    <label class="btn btn-primary">
        <input type="radio" name="options" id="option2" value="2" data-bind="checked: optionsValue"> Option 2
    </label>
    <label class="btn btn-primary">
        <input type="radio" name="options" id="option3" value="3" data-bind="checked: optionsValue"> Option 3
    </label>
</div>
<br />
<span data-bind="text: optionsValue"></span>
var ViewModel = function() {
    this.optionsValue = ko.observable()
};

ko.applyBindings(new ViewModel());
JsFiddle:

<div class="btn-group" data-toggle="buttons">
    <label class="btn btn-primary">
        <input type="radio" name="options" id="option1" value="1" data-bind="checked: optionsValue"> Option 1
    </label>
    <label class="btn btn-primary">
        <input type="radio" name="options" id="option2" value="2" data-bind="checked: optionsValue"> Option 2
    </label>
    <label class="btn btn-primary">
        <input type="radio" name="options" id="option3" value="3" data-bind="checked: optionsValue"> Option 3
    </label>
</div>
<br />
<span data-bind="text: optionsValue"></span>
var ViewModel = function() {
    this.optionsValue = ko.observable()
};

ko.applyBindings(new ViewModel());
  • 无数据切换:
  • 使用数据切换:

我有上面的代码,我正试图让工作,因为我期望它。问题在于,当将
data toggle=“buttons”
添加到btn组div(如中所示)时,淘汰绑定停止工作。如果我关闭按钮组的数据切换,那么绑定会按预期工作,但按钮组看起来很糟糕。我知道这在Bootstrap 2中不起作用,因为他们实际上没有使用收音机输入来设计收音机样式。为什么它现在拒绝工作,即使他们这样做了?

和绑定仍然不好:

  • 敲除使用选中的
    绑定中的
    单击
    事件来跳跳虎可观察到的基线进行更改
  • bootstrap订阅click事件以进行切换,但调用
    e.preventDefault()
    因此不会通知KO单击
一种可能的解决方案是创建一个自定义绑定处理程序,您可以在其中订阅
change
事件(这是由toogle上的bootstrap触发的),并在其中设置您的observables值:

ko.bindingHandlers.bsChecked = {
    init: function (element, valueAccessor, allBindingsAccessor,
    viewModel, bindingContext) {
        var value = valueAccessor();
        var newValueAccessor = function () {
            return {
                change: function () {
                    value(element.value);
                }
            }
        };
        ko.bindingHandlers.event.init(element, newValueAccessor,
        allBindingsAccessor, viewModel, bindingContext);
    },
    update: function (element, valueAccessor, allBindingsAccessor,
    viewModel, bindingContext) {
        if ($(element).val() == ko.unwrap(valueAccessor())) {
             setTimeout(function () {
                $(element).closest('.btn').button('toggle');
             }, 1); 
        }
    }
}
并在您的视图中使用它:

<label class="btn btn-primary">
    <input type="radio" name="options" id="option1" value="1" 
           data-bind="bsChecked: optionsValue"> Option 1
</label>

选择1
使用Bootstrap 3.0.2的原始演示
使用Bootstrap 3.2.0更新了演示版,我不能相信这一点,因为我的同事曾经提出过,但效果非常好

<div class="btn-group" data-toggle="buttons">
    <label data-bind="css: { active: !HideInLeaderboards() }, 
                      click: function () { HideInLeaderboards(false); },
                      clickBubble: false" 
                      class="btn btn-default">
        Show Name
    </label>
    <label data-bind="css: { active: HideInLeaderboards() },
                      click: function () { HideInLeaderboards(true); },
                      clickBubble: false" class="btn btn-default">
        Hide Name
    </label>
</div>

显示名称
隐藏名称

将@nemesv建议的处理程序更改为:它在我的应用程序中运行良好

ko.bindingHandlers.bsChecked = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var value = valueAccessor();
        var newValueAccessor = function () {
            return {
                change: function () {
                    value(element.value);
                }
            }
        };
        if ($(element).val() == ko.unwrap(valueAccessor())) {
            $(element).closest('.btn').button('toggle');
        }
        ko.bindingHandlers.event.init(element, newValueAccessor, allBindingsAccessor, viewModel, bindingContext);
    }
}
似乎是引导和淘汰之间的绑定,并且似乎保持了相当好的最新状态。具体而言,单选按钮使用以下代码:

// Knockout checked binding doesn't work with Bootstrap radio-buttons
ko.bindingHandlers.radio = {
    init: function (element, valueAccessor) {

        if (!ko.isObservable(valueAccessor())) {
            throw new Error('radio binding should be used only with observable values');
        }

        $(element).on('change', 'input:radio', function (e) {
            // we need to handle change event after bootsrap will handle its event
            // to prevent incorrect changing of radio button styles
            setTimeout(function() {
                var radio = $(e.target),
                    value = valueAccessor(),
                    newValue = radio.val();

                value(newValue);
            }, 0);
        });
    },

    update: function (element, valueAccessor) {
        var $radioButton = $(element).find('input[value="' + ko.unwrap(valueAccessor()) + '"]'),
            $radioButtonWrapper;

        if ($radioButton.length) {
            $radioButtonWrapper = $radioButton.parent();

            $radioButtonWrapper.siblings().removeClass('active');
            $radioButtonWrapper.addClass('active');

            $radioButton.prop('checked', true);
        } else {
            $radioButtonWrapper = $(element).find('.active');
            $radioButtonWrapper.removeClass('active');
            $radioButtonWrapper.find('input').prop('checked', false);
        }
    }
};

有一种更容易找到的方法

我们不能使用
数据切换
属性,而尝试使用knockout的数据绑定实现相同的行为

它几乎和本地html收音机一样简单

var ViewModel=function(){
this.optionsValue=ko.可观察(“1”);
};
应用绑定(新的ViewModel())
input[type=“radio”]{
/*使本机收音机的行为与引导程序的收音机相同*/
显示:无;
}

选择1
选择2
选择3


这里有一个简单的解决方案,我很惊讶还没有提到

1) 从btn组中删除
data toggle=“buttons”

现在淘汰赛应该开始了

2) Bootstrap为这些输入应用自定义css以隐藏它们,我们刚刚删除了数据切换,因此将以下css应用于收音机输入

position: absolute;
clip: rect(0,0,0,0);
pointer-events: none;
data-bind="css: {active: optionsValue() == valueOfThisInput}"
3) 我们需要的最后一件事是使所选选项的按钮具有活动类。将以下内容添加到标签按钮中:

position: absolute;
clip: rect(0,0,0,0);
pointer-events: none;
data-bind="css: {active: optionsValue() == valueOfThisInput}"

Bootstrap toogle按钮仍然不能很好地处理KO,因此您需要一个类似这样的自定义绑定处理程序:注意,使用此代码的单选按钮组在Bootstrap 2.x中工作正常(尽管它们也在“按钮”中显示单选按钮本身,除非您自己将其隐藏)。这是因为Bootstrap 2.x代码没有试图拦截点击-它更喜欢模拟相同的行为。@Kittoes你应该问问它……哈哈,对不起,伙计。我只是想知道这背后是否有一些明显的原因,因为我对javascript这玩意儿还很陌生。你的回答很有效,很遗憾这样的事情是必要的。我很好奇,除了单选按钮外,人们如何在一个复选框中使用它。非常好的帖子!下面是复选框按钮组的一个修改:@Matus这里有类似的问题。数据正常,但BS和KO都会切换该值。添加&$(element).prop('checked')条件来更新甲烷储罐的固定状态,这对于使用相同可观测值的多个链接切换非常有效!