Nested template
https://groups.google.com/d/topic/knockoutjs/YJX42gLJ3l8/discussion
by gurkavcu
HTML
<script src="http://github.com/downloads/SteveSanderson/knockout/jquery.tmpl.js"></script>
<script src="http://knockoutjs.com/js/knockout-1.2.1.js"></script>
<ul data-bind="template: { name: 'nodeTmpl', foreach: nodes }"></ul>
<script id="nodeTmpl" type="text/html">
<li>
<div data-bind="text: name"></div>
<ul data-bind="template: { name: 'nodeTmpl', foreach: children }"></ul>
</li>
</script>
<br/><br/>
<a id="call" href="#" >Add New Node</a>
CSS
ul { margin-left: 10px; }
JavaScript
var dataFromServer = [
{
name: "root",
parent: null},
{
name: "a",
parent: "root"},
{
name: "a1",
parent: "a"},
{
name: "a2",
parent: "a"},
{
name: "b",
parent: "root"},
{
name: "b1",
parent: "b"},
{
name: "b1a",
parent: "b1"}
];
function Node(name, children) {
this.name = ko.observable(name);
this.children = ko.observableArray(children || []);
}
function getMappedData(data) {
var result = [];
var index = {};
//build an index of Node objects to avoid looping, unless you can depend on the order always having parents first in the data
ko.utils.arrayForEach(data, function(node) {
index[node.name] = new Node(node.name);
});
//assign nodes to their parents, if their is no parent assign it to the resulting array
ko.utils.arrayForEach(data, function(node) {
if (node.parent) {
index[node.parent].children.push(index[node.name]);
} else {
result.push(index[node.name]);
}
});
return result;
}
var viewModel = {
nodes: ko.observableArray(getMappedData(dataFromServer))
};
ko.applyBindings(viewModel);
$(document).ready(function() {
updateNode = function() {
var root = viewModel.nodes()[0];
var bchilds = root.children()[1].children();
var newNode = new Node('c');
bchilds.push(newNode);
console.log(ko.toJSON(viewModel));
// ko.applyBindings(viewModel);
};
$('#call').click(updateNode);
});