KO v3.3 Component Elements

Wrapping components in templates!

by Mark

HTML

<script src="http://knockoutjs.com/downloads/knockout-3.3.0.js"></script>
<h1>Component Template Demo</h1>

<p>The aim of this fiddle is to demonstrate putting a wrapping template around a widget that is bound to the same viewmodel. It uses the new Knockout v3.3 features $componentTemplateNodes, and the template: {nodes .. } binding.</p>
<p>In the example below, we have two components, editor1 and editor2 - these use a common-template and inject their own version of the editing control inside this template.</p>
<editor1 params='value: Value1, label: "Name (text)"'></editor1>
<editor2 params='value: Value2, label: "Active (check)"'></editor2>
<hr/>
<b>JSON:</b>

<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>

CSS

.box {
    display:block;
    padding: 10px;
    border: 1px solid #444;
    background-color: #eef;
}
.input {
    display: block;
    margin-left: 100px;
}
.label {
    color: blue;
    float: left;
    margin-left: 0px;
    max-width: 100px;
}

JavaScript

ko.components.register("common-template", {
    viewModel: {
        createViewModel: function (params, componentInfo) {
            //reuse viewmodel of parent
            return params.data;
        }
    },
    template: "<div class=\"box\"><label class=\"label\" data-bind='text: Label'></label><div class=\"input\" data-bind=\"template: { nodes: $componentTemplateNodes, data: $data }\"></div>"
});

/* first editor uses a textbox */
ko.components.register("editor1", {
    viewModel: function (params) {
        var self = this;
        self.Label = ko.observable(params.label);
        self.Value = params.value;
    },
    template: "<common-template params='data: $data'><input type='text' data-bind='value: Value' /></common-template>"
});

/* second editor uses a checkbox */
ko.components.register("editor2", {
    viewModel: function (params) {
        var self = this;
        self.Label = ko.observable(params.label);
        self.Value = params.value;
    },
    template: "<common-template params='data: $data'><input type='checkbox' data-bind='checked: Value' /></common-template>"
});

// main viewmodel
var viewModel = function () {
    var self = this;
    // two values, string and boolean
    self.Value1 = ko.observable("hello world");
    self.Value2 = ko.observable(true);
};

ko.applyBindings(new viewModel());