KO Popover Labels
Show how to bind knockout to the contents of a Bootstrap popover
by Jason Butz
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.3.7/js/tether.min.js"></script>
<script src=" https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<div class="container" style="margin-top: 80px;">
<!-- ko template: {afterRender: afterRender} -->
<button class="btn btn-lg btn-primary" data-bind="attr:{ id: btnId}" data-toggle="popover" data-contentx="Hello World">
Click Me
</button>
<!-- /ko -->
<pre id="output"></pre>
</div>
<script id="demoPopoverTemplate" type="text/template">
<div>
<span>Hello World!</span>
<div data-bind='foreach: popoverLabels'>
<div>
<input type="checkbox" data-bind="checked: selected">
<span class="" data-bind="text: text"></span>
</div>
</div>
</div>
</script>
SCSS
@import url(https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.min.css);
#output {
margin-top: 25px;
height: 500px;
}
JavaScript
class App {
constructor() {
this.btnId = Date.now();
this.showType = 'TEAM';
this.myLabels = ko.observableArray([
{
text: ko.observable('One'),
selected: ko.observable(false),
type: ko.observable('TEAM')
},
{
text: ko.observable('Two'),
selected: ko.observable(true),
type: ko.observable('PROJECT')
},
{
text: ko.observable('Three'),
selected: ko.observable(true),
type: ko.observable('TEAM')
}
]);
this.popoverLabels = ko.pureComputed(() => {
return this.myLabels().filter((label) => {
label.selected(); // Bind the computed to this value
return label.type() === this.showType;
})
})
.extend({ rateLimit: { timeout: 1000, method: "notifyWhenChangesStop" } });
this.popoverLabels.subscribe(() => {
this.save();
});
}
save() {
var outputEl = document.getElementById('output');
var contents = outputEl.innerText;
contents += `${Date()} | ${ko.toJSON(this.myLabels)}\n`;
outputEl.innerText = contents;
}
afterRender(elements, viewModel) {
// We need to have a single DOM element that contains everything we want in the popover
// A div with nothing on it should be fine
// Here I am using jQuery to create the DOM elements for me
// from a string. It doesn't matter how they are created, they
// just must be DOM elements for KO to do the magic
// Get the template element
var templateEl = document.getElementById('demoPopoverTemplate');
// Turn the template element's contents into a jquery object then extract the DOM
// elements
var content = $(templateEl.innerText).get(0);
// Set the content for a our...