twitter-bootstrap 淘汰赛 + Bootstrap 3 单选按钮
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20077475/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Knockout + Bootstrap 3 Radio Buttons
提问by Kittoes0124
Related to: Bootstrap Radio Button Group
HTML:
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>
Javascript:
Javascript:
var ViewModel = function() {
this.optionsValue = ko.observable()
};
ko.applyBindings(new ViewModel());
JsFiddle:
JsFiddle:
- Without data-toggle: http://jsfiddle.net/fDMM2/
- With data-toggle: http://jsfiddle.net/Kf3tj/1/
- 没有数据切换:http: //jsfiddle.net/fDMM2/
- 随着数据切换:http: //jsfiddle.net/Kf3tj/1/
I have the above code which I'm trying to get working as I expect it to. The problem is that when data-toggle="buttons"is added to the btn-group div (as in the Bootstrap 3 example) the knockout binding stops working. If I leave the data-toggle off of the buttons group then the binding works as expected but the button group looks awful. I know that this didn't work in Bootstrap 2 because they didn't actually use the radio input for their radio styling. How come it refuses to work now even though they do?
我有上面的代码,我正在尝试按照我的预期工作。问题是当data-toggle="buttons"被添加到 btn-group div(如在Bootstrap 3 示例中)时,淘汰赛绑定停止工作。如果我离开按钮组的数据切换,那么绑定会按预期工作,但按钮组看起来很糟糕。我知道这在 Bootstrap 2 中不起作用,因为他们实际上并没有将收音机输入用于收音机样式。为什么它现在拒绝工作,即使他们这样做了?
回答by nemesv
The bootstrap buttonsand the knockout checkedbinding are still not playing nice:
在引导按钮和淘汰赛checked结合仍然没有踢得好看:
- knockout uses the
clickevent inside thecheckedbinding to tigger the underlaying observable to change - bootstrap subscribes on the click event to do the toggling but calls
e.preventDefault()so KO won't be notified about the click.
- 淘汰赛使用绑定
click内的事件checked来触发底层 observable 改变 - bootstrap 订阅 click 事件以进行切换但调用,
e.preventDefault()因此 KO 不会收到有关点击的通知。
One possible solution is to create a custom binding handler where you subscribe on the changeevent (this is fired by bootstrap on toogle) and set your observables value there:
一种可能的解决方案是创建一个自定义绑定处理程序,您可以在其中订阅change事件(这是由工具上的引导程序触发的)并在那里设置您的 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);
}
}
}
And use it in your view with:
并在您的视图中使用它:
<label class="btn btn-primary">
<input type="radio" name="options" id="option1" value="1"
data-bind="bsChecked: optionsValue"> Option 1
</label>
Original demo using Bootstrap 3.0.2JSFiddle.
Updated demo using Bootstrap 3.2.0JSFiddle.
使用Bootstrap 3.0.2 JSFiddle 的原始演示。
使用Bootstrap 3.2.0 JSFiddle更新演示。
回答by Matthew Will
I can't take credit for this since once on my coworkers came up with it but it works really well.
我不能相信这一点,因为有一次我的同事想出了它,但它真的很好用。
<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>
回答by J3soon
There is a much easier approach found here.
有发现一个更容易的方法在这里。
We can just not use the data-toggleattribute and try to achieve the same behavior using knockout's data binding.
我们可以不使用该data-toggle属性并尝试使用淘汰赛的数据绑定来实现相同的行为。
It's almost as simple as the native html radios.
它几乎和原生 html 收音机一样简单。
var ViewModel = function() {
this.optionsValue = ko.observable("1");
};
ko.applyBindings(new ViewModel());
input[type="radio"] {
/* Make native radio act the same as bootstrap's radio. */
display: none;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="btn-group">
<label class="btn btn-primary" data-bind="css: {active: optionsValue() == '1'}">
<input type="radio" name="options" id="option1" value="1" data-bind="checked: optionsValue">Option 1
</label>
<label class="btn btn-primary" data-bind="css: {active: optionsValue() == '2'}">
<input type="radio" name="options" id="option2" value="2" data-bind="checked: optionsValue">Option 2
</label>
<label class="btn btn-primary" data-bind="css: {active: optionsValue() == '3'}">
<input type="radio" name="options" id="option3" value="3" data-bind="checked: optionsValue">Option 3
</label>
</div>
<br/>
<span data-bind="text: optionsValue"></span>
回答by danatcofo
change the handler @nemesv proposed to be this: and it worked in my app just fine.
将@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);
}
}
回答by CC Inc
Knockstrapappears to be a binding between Bootstrap and Knockout, and it appears to be kept pretty well up to date. Concerning radio buttons in specific, they utilize this code:
Knockstrap似乎是 Bootstrap 和 Knockout 之间的绑定,并且它似乎一直保持最新状态。关于具体的单选按钮,他们使用以下代码:
// 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);
}
}
};
回答by izzy
There's a simple solution here that I'm surprised hasn't been mentioned yet.
这里有一个简单的解决方案,我很惊讶还没有提到。
1) Remove the data-toggle="buttons"from the btn-group
1)data-toggle="buttons"从btn-group 中删除
Now knockout should be working
现在淘汰赛应该有效
2) Bootstrap applies custom css for these inputs to hide them, that we just lost by removing the data-toggle, so apply the following css to the radio inputs:
2) Bootstrap 为这些输入应用自定义 css 以隐藏它们,我们刚刚通过删除数据切换丢失了它们,因此将以下 css 应用于无线电输入:
position: absolute;
clip: rect(0,0,0,0);
pointer-events: none;
3) Last thing we need is for the selected option's button to have the active class. Add the following to the label buttons:
3)我们需要的最后一件事是使所选选项的按钮具有活动类。将以下内容添加到标签按钮:
data-bind="css: {active: optionsValue() == valueOfThisInput}"

