Knockout - 将样式应用于 Bootstrap Select 中的选定项目
Knockout - applying styles to the selected item in a Bootstrap Select
所以这是在库之上叠加库,但我不确定还能做什么。
我们的应用程序有许多下拉元素,它们都是 Bootstrap Select 对象。这些将 select 中的标准选项标签集替换为一系列复杂的其他元素,使您可以更好地控制子项的样式并使它们可搜索。
这些对象中的大多数作为可重用组件存在,具有 HTML 视图和 Typescript ViewModel,与 Knockout 绑定在一起。
其中许多菜单的文字旁边都有图标。这是用 optionsAfterRender 处理的。这是一个例子。
查看:
<select
data-bind="options: items,
value: selectedValue,
optionsText: 'value',
optionsValue: 'id',
selectPicker: {},
optionsAfterRender: applyOptionAttributes">
</select>
视图模型:
export default class SelectComponent {
selectedValue: KnockoutObservable<string>;
items: KnockoutObservableArray<SelectOption>
constructor(koObservable: KnockoutObservable<string>) {
// items fetched and bound
}
applyOptionAttributes(option: Node, item: SelectOption): void {
ko.applyBindingsToNode(option, { attr: { "data-content": `<img src="${item.iconurl}" />`, title: item.value } }, item);
}
}
interface SelectOption {
value: string;
id: string
iconurl: string;
}
这很好。但是,由于 Bootstrap Select 中项目的样式,图标不会应用于当前 selected 项目 - 它仅在用户单击菜单时显示并且它弹出。
现在,当然,我们也需要在当前 selected 项目中显示图标。但我不知道如何让该元素绑定到它。由于视图-视图模型模式,我无法直接获取它。它似乎不在 optionsAfterRender 传递的节点中。
我怎样才能拿到它来设计它的样式?
编辑:很确定这是 bootstrap-select 中的错误。已提出问题
https://github.com/snapappointments/bootstrap-select/issues/2129
您可以尝试通过阻止选项的 post 处理来解决此问题:
- 将
options
绑定替换为 select
元素中的 foreach
绑定,将每个 option
绑定到适当的 ko 绑定。
- 在元素上调用
selectpicker
之前,请确保 selectPicker 绑定具有其 descendant bindings 绑定。
- 盈利!
ko.bindingHandlers['selectPicker'] = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.applyBindingsToDescendants(bindingContext, element);
$(element).selectpicker();
return { controlsDescendantBindings: true };
}
}
ko.applyBindings({
selectedValue: ko.observable(3),
options: [
{ id: 1, name: 'Mustard', dc: '<span class="badge badge-warning">Mustard</span>' },
{ id: 3, name: 'Ketchup', dc: '<span class="badge badge-danger">Ketchup</span>' },
{ id: 4, name: 'Relish', dc: '<span class="badge badge-success">Relish</span>' }
]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.3/css/bootstrap-select.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.3/js/bootstrap-select.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="selectPicker, value: selectedValue">
<!-- ko foreach: options -->
<option data-bind="text: name, attr: { value: id, 'data-content': dc }"></option>
<!-- /ko -->
</select>
所以这是在库之上叠加库,但我不确定还能做什么。
我们的应用程序有许多下拉元素,它们都是 Bootstrap Select 对象。这些将 select 中的标准选项标签集替换为一系列复杂的其他元素,使您可以更好地控制子项的样式并使它们可搜索。
这些对象中的大多数作为可重用组件存在,具有 HTML 视图和 Typescript ViewModel,与 Knockout 绑定在一起。
其中许多菜单的文字旁边都有图标。这是用 optionsAfterRender 处理的。这是一个例子。
查看:
<select
data-bind="options: items,
value: selectedValue,
optionsText: 'value',
optionsValue: 'id',
selectPicker: {},
optionsAfterRender: applyOptionAttributes">
</select>
视图模型:
export default class SelectComponent {
selectedValue: KnockoutObservable<string>;
items: KnockoutObservableArray<SelectOption>
constructor(koObservable: KnockoutObservable<string>) {
// items fetched and bound
}
applyOptionAttributes(option: Node, item: SelectOption): void {
ko.applyBindingsToNode(option, { attr: { "data-content": `<img src="${item.iconurl}" />`, title: item.value } }, item);
}
}
interface SelectOption {
value: string;
id: string
iconurl: string;
}
这很好。但是,由于 Bootstrap Select 中项目的样式,图标不会应用于当前 selected 项目 - 它仅在用户单击菜单时显示并且它弹出。
现在,当然,我们也需要在当前 selected 项目中显示图标。但我不知道如何让该元素绑定到它。由于视图-视图模型模式,我无法直接获取它。它似乎不在 optionsAfterRender 传递的节点中。
我怎样才能拿到它来设计它的样式?
编辑:很确定这是 bootstrap-select 中的错误。已提出问题
https://github.com/snapappointments/bootstrap-select/issues/2129
您可以尝试通过阻止选项的 post 处理来解决此问题:
- 将
options
绑定替换为select
元素中的foreach
绑定,将每个option
绑定到适当的 ko 绑定。 - 在元素上调用
selectpicker
之前,请确保 selectPicker 绑定具有其 descendant bindings 绑定。 - 盈利!
ko.bindingHandlers['selectPicker'] = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.applyBindingsToDescendants(bindingContext, element);
$(element).selectpicker();
return { controlsDescendantBindings: true };
}
}
ko.applyBindings({
selectedValue: ko.observable(3),
options: [
{ id: 1, name: 'Mustard', dc: '<span class="badge badge-warning">Mustard</span>' },
{ id: 3, name: 'Ketchup', dc: '<span class="badge badge-danger">Ketchup</span>' },
{ id: 4, name: 'Relish', dc: '<span class="badge badge-success">Relish</span>' }
]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.3/css/bootstrap-select.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.3/js/bootstrap-select.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="selectPicker, value: selectedValue">
<!-- ko foreach: options -->
<option data-bind="text: name, attr: { value: id, 'data-content': dc }"></option>
<!-- /ko -->
</select>