使用Bootstrap和#KnockoutJS将单选按钮替换为按钮组

问题

单选按钮很难看到,不容易选择,让我们面对它,相当平凡。您可能想用一组具有相同功能的按钮来替换这些单选按钮,例如,在任何给定的时间只能选择其中一个选项。

解决方案

利用Bootstrap,它为按钮、警告框、表格、表单等提供了许多令人难以置信的样式组件,常规的单选按钮将被一个按钮组取代(见下面的截图)。js将用于创建一个定制的数据绑定,它将使这组按钮像常规的单选按钮一样工作(当然有更好的外观)。

radiobuttongroup

这个例子假设您对Bootstrap和Knockout.js都有基本的了解。

本例使用的版本是Bootstrap的3.3.4和Knockout.js的3.3。这个示例应该与这些框架的旧版本兼容。

讨论

在开始之前,必须设置所需的框架。Bootstrap可以通过他们的CDN安装或下载。这个例子将使用CDN;但是,我建议您使用最适合您需要的选项。js已经被下载并保存到与示例相同的位置。确保根据项目的位置更新此位置。最后,在敲除定制绑定中使用了一点jQuery。再一次,这个例子利用了CDN;但是,如果你喜欢,你可以下载并包含它。

要使这个示例工作,它需要两个条件。一组按钮,如果它们是单选按钮,将包含哪些选项,以及将在数据绑定中使用的敲除可观察值。这个可观察对象将包含选中的选项。下面包含HTML标记和非常基本的Knockout ViewModel。

<html>
<head>
<linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
</head>
<body>
<divclass="btn-group">
<buttontype="button"class="btn btn-default"data-bind="radioButtonGroup: selectedOption, radioValue: 'option1'">Option 1</button>
<buttontype="button"class="btn btn-default"data-bind="radioButtonGroup: selectedOption, radioValue: 'option2'">Option 2</button>
<buttontype="button"class="btn btn-default"data-bind="radioButtonGroup: selectedOption, radioValue: 'option3'">Option 3</button>
</div>

<scriptsrc="knockout.js"></script>
<scriptsrc="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script>
function ViewModel() {
var self = this;

self.selectedOption = ko.observable();
};

var viewModel = new ViewModel();
ko.applyBindings(viewModel);
</script>
</body>
</html>

这个例子现在还不能工作。如果仔细观察,就会发现每个HTML按钮都包含一个名为radioButtonGroup的数据绑定(马上就会定义)。这是将完成我们的按钮组的定制数据绑定。提供给新数据绑定的是可观察变量,它被恰当地命名为selectedOption。第二个值也被命名为radioValue。这应该设置为用户按下按钮时希望selectedOption变量包含的值。

要完成这个示例,需要创建自定义绑定。在ko下添加自定义绑定。bindingHandlers名称空间。绑定处理程序是通过创建init和update函数定义的。两者都是可选的,但至少必须定义一个。当Knockout是绑定到页面的第一个数据时,将调用init函数。你可以在这里创建事件监听器等等。每次值更改时(包括第一次加载时)都会调用update函数。如果您希望在每次值更改时执行特定的操作,则将使用此函数。

radioButtonGroup自定义绑定只需要init函数,因为单击事件的事件监听器将用于跟踪所有更改。下面的JavaScript代码应该在包含Knockout框架之后,但在定义ViewModel和应用Knockout绑定之前放置(或从一个单独的文件中包含)。

<script>
ko.bindingHandlers.radioButtonGroup = {
init: function (element, valueAccessor, allBindings, viewModel, 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));
$btn.toggleClass("btn-info", observable() === ko.utils.unwrapObservable(radioValue));
}
});
});
}
};
</script>

init函数接受5个参数。被数据绑定的元素,也是数据绑定的变量,这个元素上的所有其他绑定,整个ViewModel(尽管这是不赞成的),还有bindingContext,这是通过使用bindingContext.$data来访问ViewModel的新方法。

在init函数内部,它首先验证它正在处理一个可观察属性。通过使用带有数据绑定的HTML元素(和一些jQuery),可以找到相关的按钮并存储在一个变量中。然后循环使用这些按钮,并侦听单击事件。当它发生时,与数据绑定值相关联的可观察属性将使用所选选项更新。最后定义一个计算变量,如果可观察对象的值等于按钮的值,则添加类active和btn-info来标识当前选择的按钮。

这就完成了本示例,一如既往,您可以在GitHub上找到完整的源代码。

本文转载于:http://www.diyabc.com/frontweb/news14015.html

原文地址:https://www.cnblogs.com/Dincat/p/13485268.html