Bootstrap 切换按钮的淘汰赛绑定
Knockout binding for Bootstrap toggle buttons
我正在寻找一种在 KnockoutJS 中将切换按钮绑定到选择特定值(按钮)时调用的函数的方法。
我尝试了几种解决方案并得到它 运行 只是 KnockoutJS,但是当我向它添加 Boostrap 时,它仍然不起作用。
此处显示的我的代码不会触发与 checked
事件关联的处理函数。对于最新的工作示例,请使用 JSFiddle。
HTML:
<div id="access-rights-control" class="btn-group pull-right" data-toggle="buttons">
<label class="btn btn-xs">
<input type="radio" name="status" value="1" id="status-published" data-bind="checked: $root.allowAccessHandler" />Allow access
</label>
<label class="btn btn-xs active">
<input type="radio" name="status" value="0" id="status-draft" checked /> No change
</label>
</div>
JS:
var viewModel = function() {
this.allowAccessHandler = function() {
alert("Works!");
}
};
ko.applyBindings(new viewModel());
JSFiddle:
http://jsfiddle.net/p8nSe/191/
也许您想要的就像下面的代码片段所做的那样。请查看并给我反馈。
ko.bindingHandlers["bsChecked"] ={
init: function(element, valueAccessor){
ko.utils.registerEventHandler(element,"change",function(event){
var check = $(event.target);
valueAccessor()(check.val());
});
}
};
var viewModel = function() {
this.checkedButton = ko.observable("2").extend({ notify: 'always' });
this.checkedButton.subscribe( function(checkedVal) {
// here you can decide what to do depends on the new checkedVal
alert("Works! : "+ checkedVal);
},this);
};
ko.applyBindings(new viewModel());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet"/>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="access-rights-control" class="btn-group pull-left" data-toggle="buttons">
<label class="btn btn-xs btn-default">
<input type="radio" name="status" value="1" data-bind="bsChecked: checkedButton" />Allow access
</label>
<label class="btn btn-xs btn-default">
<input type="radio" name="status" value="2" data-bind="bsChecked: checkedButton" />No change
</label>
</div>
更新
Created a binding handler to take care about the prevent changes caused by bootstrap, so this is a workaround and I suggest to you read about KO custom bindings and implement the update
function of the binding handler.
如果你想要在点击 input
时 运行 的东西,那么你需要使用 event binding not the checked 绑定(它只是将选中的状态绑定到一个可观察的状态,它是不是事件处理程序)。类似于:
var viewModel = function() {
this.allowAccessHandler = function() {
alert("Works!");
}
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="access-rights-control" class="btn-group pull-right" data-toggle="buttons">
<label class="btn btn-xs">
<input type="radio" name="status" value="1" id="status-published" data-bind="event: { change: $root.allowAccessHandler }" />Allow access
</label>
<label class="btn btn-xs active">
<input type="radio" name="status" value="0" id="status-draft" /> No change
</label>
</div>
现在,如果您将 checked
状态绑定到视图模型中的 属性,那么将 subscribe
绑定到 属性 可能会更好,而不是将事件处理程序附加到 DOM,因为这将更符合分离视图和视图模型的要求。
我认为你有两个问题:
- 您没有 Bootstrap 无线电组的绑定处理程序,这意味着您的
checked
绑定将不起作用
- 您没有正确使用
checked
绑定。
第二个我可以帮你。在所有元素具有相同 name
属性和不同 value
属性的单选组中,绑定到 checked
可观察对象的变量将获得所选单选项的值。
您可以订阅可观察对象并在它获得特定值时采取行动。
var viewModel = function() {
this.radioSelected = ko.observable();
this.radioSelected.subscribe(function(newValue) {
console.debug("Comparing", newValue, '1');
if (newValue === '1') {
alert("Works!");
}
});
this.radioSelected('0');
this.output = ko.observableArray();
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="access-rights-control" class="btn-group pull-right" data-toggle="buttons">
<label class="btn btn-xs btn-default">
<input type="radio" name="status" value="1" data-bind="checked: radioSelected" />Allow access
</label>
<label class="btn btn-xs btn-default active">
<input type="radio" name="status" value="0" data-bind="checked: radioSelected" />No change
</label>
</div>
<div data-bind="foreach:output">
<div data-bind="text:$data">
</div>
</div>
同样,如果您有 Bootstrap 样式的单选按钮,这将不起作用,因为 Bootstrap 以 Knockout 未设置为检测的方式摆弄 DOM .所以你需要a binding handler that works with Bootstrap radio magic。这可能需要您的方法略有不同(即,您可能不使用 checked
绑定)我不知道。
最后我找到了一种本机工作并完成任务的方法。我不确定它是否是最通用的,因为我必须覆盖 ko.bindingHandlers.radio
,但它有效。
ko.bindingHandlers.radio = {
init: function(element, valueAccessor, allBindings, data, context) {
var $buttons, $element, observable;
observable = valueAccessor();
if (!ko.isWriteableObservable(observable)) {
throw "You must pass an observable or writeable computed";
}
$element = $(element);
if ($element.hasClass("btn")) {
$buttons = $element;
} else {
$buttons = $(".btn", $element);
}
elementBindings = allBindings();
$buttons.each(function() {
var $btn, btn, radioValue;
btn = this;
$btn = $(btn);
radioValue = elementBindings.radioValue || $btn.attr("data-value") || $btn.attr("value") || $btn.text();
$btn.on("click", function() {
observable(ko.utils.unwrapObservable(radioValue));
});
return ko.computed({
disposeWhenNodeIsRemoved: btn,
read: function() {
$btn.toggleClass("active", observable() === ko.utils.unwrapObservable(radioValue));
}
});
});
}
};
var viewModel = function() {
this.radioSelected = ko.observable('0');
this.radioSelected.subscribe(function(newValue) {
console.debug("Comparing", newValue, '1');
if (newValue === '1') {
alert("Works!");
}
});
};
ko.applyBindings(new viewModel());
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet"/>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="btn-group">
<button type="button" class="btn" data-bind="radio: radioSelected, radioValue: '1'">Allow access</button>
<button type="button" class="btn" data-bind="radio: radioSelected, radioValue: '0'">No change</button>
</div>
JSFiddle:http://jsfiddle.net/p8nSe/192/
我正在寻找一种在 KnockoutJS 中将切换按钮绑定到选择特定值(按钮)时调用的函数的方法。
我尝试了几种解决方案并得到它 运行 只是 KnockoutJS,但是当我向它添加 Boostrap 时,它仍然不起作用。
此处显示的我的代码不会触发与 checked
事件关联的处理函数。对于最新的工作示例,请使用 JSFiddle。
HTML:
<div id="access-rights-control" class="btn-group pull-right" data-toggle="buttons">
<label class="btn btn-xs">
<input type="radio" name="status" value="1" id="status-published" data-bind="checked: $root.allowAccessHandler" />Allow access
</label>
<label class="btn btn-xs active">
<input type="radio" name="status" value="0" id="status-draft" checked /> No change
</label>
</div>
JS:
var viewModel = function() {
this.allowAccessHandler = function() {
alert("Works!");
}
};
ko.applyBindings(new viewModel());
JSFiddle: http://jsfiddle.net/p8nSe/191/
也许您想要的就像下面的代码片段所做的那样。请查看并给我反馈。
ko.bindingHandlers["bsChecked"] ={
init: function(element, valueAccessor){
ko.utils.registerEventHandler(element,"change",function(event){
var check = $(event.target);
valueAccessor()(check.val());
});
}
};
var viewModel = function() {
this.checkedButton = ko.observable("2").extend({ notify: 'always' });
this.checkedButton.subscribe( function(checkedVal) {
// here you can decide what to do depends on the new checkedVal
alert("Works! : "+ checkedVal);
},this);
};
ko.applyBindings(new viewModel());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet"/>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="access-rights-control" class="btn-group pull-left" data-toggle="buttons">
<label class="btn btn-xs btn-default">
<input type="radio" name="status" value="1" data-bind="bsChecked: checkedButton" />Allow access
</label>
<label class="btn btn-xs btn-default">
<input type="radio" name="status" value="2" data-bind="bsChecked: checkedButton" />No change
</label>
</div>
更新
Created a binding handler to take care about the prevent changes caused by bootstrap, so this is a workaround and I suggest to you read about KO custom bindings and implement the
update
function of the binding handler.
如果你想要在点击 input
时 运行 的东西,那么你需要使用 event binding not the checked 绑定(它只是将选中的状态绑定到一个可观察的状态,它是不是事件处理程序)。类似于:
var viewModel = function() {
this.allowAccessHandler = function() {
alert("Works!");
}
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="access-rights-control" class="btn-group pull-right" data-toggle="buttons">
<label class="btn btn-xs">
<input type="radio" name="status" value="1" id="status-published" data-bind="event: { change: $root.allowAccessHandler }" />Allow access
</label>
<label class="btn btn-xs active">
<input type="radio" name="status" value="0" id="status-draft" /> No change
</label>
</div>
现在,如果您将 checked
状态绑定到视图模型中的 属性,那么将 subscribe
绑定到 属性 可能会更好,而不是将事件处理程序附加到 DOM,因为这将更符合分离视图和视图模型的要求。
我认为你有两个问题:
- 您没有 Bootstrap 无线电组的绑定处理程序,这意味着您的
checked
绑定将不起作用 - 您没有正确使用
checked
绑定。
第二个我可以帮你。在所有元素具有相同 name
属性和不同 value
属性的单选组中,绑定到 checked
可观察对象的变量将获得所选单选项的值。
您可以订阅可观察对象并在它获得特定值时采取行动。
var viewModel = function() {
this.radioSelected = ko.observable();
this.radioSelected.subscribe(function(newValue) {
console.debug("Comparing", newValue, '1');
if (newValue === '1') {
alert("Works!");
}
});
this.radioSelected('0');
this.output = ko.observableArray();
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="access-rights-control" class="btn-group pull-right" data-toggle="buttons">
<label class="btn btn-xs btn-default">
<input type="radio" name="status" value="1" data-bind="checked: radioSelected" />Allow access
</label>
<label class="btn btn-xs btn-default active">
<input type="radio" name="status" value="0" data-bind="checked: radioSelected" />No change
</label>
</div>
<div data-bind="foreach:output">
<div data-bind="text:$data">
</div>
</div>
同样,如果您有 Bootstrap 样式的单选按钮,这将不起作用,因为 Bootstrap 以 Knockout 未设置为检测的方式摆弄 DOM .所以你需要a binding handler that works with Bootstrap radio magic。这可能需要您的方法略有不同(即,您可能不使用 checked
绑定)我不知道。
最后我找到了一种本机工作并完成任务的方法。我不确定它是否是最通用的,因为我必须覆盖 ko.bindingHandlers.radio
,但它有效。
ko.bindingHandlers.radio = {
init: function(element, valueAccessor, allBindings, data, context) {
var $buttons, $element, observable;
observable = valueAccessor();
if (!ko.isWriteableObservable(observable)) {
throw "You must pass an observable or writeable computed";
}
$element = $(element);
if ($element.hasClass("btn")) {
$buttons = $element;
} else {
$buttons = $(".btn", $element);
}
elementBindings = allBindings();
$buttons.each(function() {
var $btn, btn, radioValue;
btn = this;
$btn = $(btn);
radioValue = elementBindings.radioValue || $btn.attr("data-value") || $btn.attr("value") || $btn.text();
$btn.on("click", function() {
observable(ko.utils.unwrapObservable(radioValue));
});
return ko.computed({
disposeWhenNodeIsRemoved: btn,
read: function() {
$btn.toggleClass("active", observable() === ko.utils.unwrapObservable(radioValue));
}
});
});
}
};
var viewModel = function() {
this.radioSelected = ko.observable('0');
this.radioSelected.subscribe(function(newValue) {
console.debug("Comparing", newValue, '1');
if (newValue === '1') {
alert("Works!");
}
});
};
ko.applyBindings(new viewModel());
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet"/>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="btn-group">
<button type="button" class="btn" data-bind="radio: radioSelected, radioValue: '1'">Allow access</button>
<button type="button" class="btn" data-bind="radio: radioSelected, radioValue: '0'">No change</button>
</div>
JSFiddle:http://jsfiddle.net/p8nSe/192/