Bind KO to a Bootstrap Popover
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 -->
<hr />
<button class="btn btn-success btn-sm" data-bind="click: addItem">
Add List Item
</button>
</div>
<script id="demoPopoverTemplate" type="text/template">
<div>
<span>Hello World!</span>
<div data-bind='foreach: myList'>
<span class="tag tag-default" data-bind="text: $data"></span>
</div>
</div>
</script>
SCSS
@import url(https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.5/css/bootstrap.min.css);
JavaScript
class App {
constructor() {
this.btnId = Date.now();
this.myList = ko.observableArray(['One', 'Two', 'Three', 'Four']);
}
addItem(viewModel) {
viewModel.myList.push(Date.now());
}
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 popover
$(`#${viewModel.btnId}`).popover({
content: content,
html: true
});
// Run KO on those DOM elements
ko.applyBindingsToDescendants(viewModel, content);
}
}
ko.applyBindings(new App());