Knockout template Example

by David Kyle

HTML

<script src="//code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-debug.js"></script>
<!-- BEGIN Template for rendering a tool-bar -->
<script id="toolbar-template" type="text/html">
    <div data-bind="foreach: { data: Tools, as: 'tool'}" class="toolbar">
        <h2 class="toolbar-title" data-bind="text: ToolbarTitle"></h2>
        <ul data-bind="foreach: {data: tool.Buttons, as: 'button'}">
            <li>
                <a data-bind="attr: { href: button.Href }, text: button.Text, click: button.ClickAction"></a>
            </li>
        </ul>
    </div>
</script>
<!-- END -->
<section>
    <h1 data-bind="text: Title"></h1>
    <div class="menu-bars" data-bind="template: 'toolbar-template'">

    </div>
</section>

CSS

body {
    color: #232323;
    font-size: small;
    background-color: #efefef;
    padding: 0px;
    margin: 0px;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.toolbar {
    margin: 2px auto;
    display: block;
    background-color: #565656;
    padding: 2px;
    border-radius: 2px;
    max-width: 80%;
}
.toolbar-title {
    border-bottom: solid 1px rgba(190,190,190,.4);
    margin: 1px;
    padding: 0px;
    vertical-align: middle;
}
.toolbar ul {
    list-style-type: none;
    display: block;
    margin: 2px;
}
.toolbar li {
    display: inline-block;
    min-width: 20%;
    max-width: 300px;
    padding: 0px;
    margin: 0px 0px;
}
.toolbar {
    color: #ababab;
}
.toolbar a {
    background-color: #ababab;
    border-radius: 2px;
    margin: 0px 1px;
    text-align: center;
    display: block;
    color: #436789;
}
.toolbar a:visited {
    color: #674389;
}
.toolbar a:hover {
    text-decoration: none;
}

JavaScript

// ViewModel class that represents the data or view model used to render a button
var Button = function() {
    var self = this; // local 'this' handle
    self.Href = ko.observable(""); // an observable property containing hyperlink data
    self.Text = ko.observable(""); // an observable property containing text to display
    self.Target = ko.observable(""); // an observable property containing the link target (_blank, _self, etc...)
    self.ClickAction = function(operation) { // Delegate for click actions
        // Simply a delegate of sorts with no default
    }
} // end class Button

// ViewModel class that represents a tool bar.  Mostly, this just contains buttons.
var Toolbar = function() {
    var self = this;
    self.Buttons = ko.observableArray([]); // observable array that mutates infrequently
    var buttons = Array(); // internal array that mutates frequently
    self.AddButton = function(href, text, target, clickOperation) {
        var button = new Button(); // initialize a new "instance" of the Button "class"
        button.Href(href);
        button.Text(text);
        button.Target(target);
        button.ClickAction = clickOperation;
        buttons.push(button);
        self.Buttons(buttons);
    };
    self.ToolbarTitle = ko.observable("");
} // end class Toolbar

// Base ViewModel applied to the whole page to make bindings less complex.  Also contains the ToolBars
var ViewModel = function() {
    var self = this;
    self.Tools = ko.observableArray([]);
    self.Title = ko.observable("");
    var tools = Array();
    self.AddToolbar = function(bar) {
        tools.push(bar);
        self.Tools(tools);
    }
} // end class ViewModel

// Utility library used to simplify building view models and other UI related data.
var Utilities = (function() {
    var root = this;
    var factories = (function() {
        var self = this;

        // function that serves as a factory for creating new toolbar instances
        self.createToolbar =...