相关:Bootstrap Radio Button Group
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:
var ViewModel = function() {
this.optionsValue = ko.observable()
};
ko.applyBindings(new ViewModel());
的jsfiddle:
我有上面的代码,我正在尝试按预期工作。问题是当data-toggle="buttons"
添加到btn-group div时(如Bootstrap 3 example中所述),敲除绑定会停止工作。如果我将数据切换关闭按钮组,则绑定按预期工作,但按钮组看起来很糟糕。我知道这在Bootstrap 2中不起作用,因为他们实际上没有使用无线电输入来进行无线电造型。为什么现在它拒绝工作呢?
答案 0 :(得分:49)
bootstrap buttons和knockout checked
绑定仍然没有发挥出色:
click
绑定中的checked
事件来触发要更改的underlaying observable 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>
使用 Bootstrap 3.0.2 JSFiddle进行原创演示 使用 Bootstrap 3.2.0 JSFiddle更新了演示。
答案 1 :(得分:15)
我不能相信这一点,因为一旦我的同事提出它,但它的效果非常好。
<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>
答案 2 :(得分:1)
更改处理程序@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);
}
}
答案 3 :(得分:1)
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);
}
}
};
答案 4 :(得分:1)
找到here的方法要容易得多。
我们不能只使用data-toggle
属性,而是尝试使用基因剔除的数据绑定来实现相同的行为。
这几乎与本地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>
答案 5 :(得分:0)
这里有一个简单的解决方案,令我惊讶的是尚未提及。
1)从 btn组
中删除data-toggle="buttons"
现在淘汰赛应该可以正常工作
2)Bootstrap对这些输入应用自定义css以隐藏它们,而我们只是通过删除数据切换而丢失了它们,因此将以下css应用于无线电输入:
position: absolute;
clip: rect(0,0,0,0);
pointer-events: none;
3)我们最后需要做的是使选定选项的按钮具有活动的类。将以下内容添加到标签按钮:
data-bind="css: {active: optionsValue() == valueOfThisInput}"