Recursive template with knockout js

Is it possible to create a recursive template only with knockout js?

I have a knockout object:

function FormElementNode(children, text, value) {
   var self = this;
   self.children = ko.observableArray(children);
   self.text = ko.observable(text);
   self.value = ko.observable(value);

children is an array of FormElementNode.

I want to draw it and it's children recursively in a hierarchy list nodes:

   <li>Parent text value:
         <li>Child1 text value</li>
         <li>Child2 text value</li>



Yes KnockOut supports recursive templates so you can reference and render the same template inside the template.

An example html in your case would look like this:

<script id="formElementNodeTemplate" type="text/html">
    <li>Parent <span data-bind="text: text"></span> 
               <span data-bind="text: value"></span>
        <!-- ko template: { name: 'formElementNodeTemplate',  
                            foreach: children } -->
        <!-- /ko -->        

<div data-bind="template: { name: 'formElementNodeTemplate', data: $data }">

Demo JSFiddle.

I think, I have a little better solution with no tree root. Please take a look:


<script id="treeElement" type="text/html">
        <span data-bind="text: name"></span>
        <ul data-bind="template: { name: 'treeElement', foreach: children }">

<ul data-bind="template: { name: 'treeElement', foreach: $data.treeRoot }"></ul>


var viewModel = {
    treeRoot: ko.observableArray()

var TreeElement = function(name, children) {
   var self = this;
   self.children = ko.observableArray(children); = ko.observable(name);

var tree = [
    new TreeElement("Russia", [
        new TreeElement("Moscow")
    new TreeElement("United States", 
        new TreeElement("New York", [ 
            new TreeElement("Harlem"),
            new TreeElement("Central Park")



Hope it helps!

This post was a great help to me. I am always finding new ways to use knockout. I just wanted to add one useful modification which is doing exactly what nemesv proposed only using the ko.mapping plugin.

//Nested javascript object:
var formElementNode = {
    children: [{
        children: [],
        text: 'Child1',
        value: 'Value1'
    }, {
        children: [{
            children: [{
                children: [],
                text: 'Child2.1.1',
                value: 'Value2.1.1'
            text: 'Child2.1',
            value: 'Value2.1'
        text: 'Child2',
        value: 'Value2'
    }, {
        children: [],
        text: 'Child3',
            value: 'Value3'
    text: 'Main',
    value: 'MainValue'

//Use ko.mapping to generate viewModel:
var viewModel = ko.mapping.fromJS(formElementNode);

As demonstrated in this jsFiddle.

Recursive Custom Binding

Another solution, after reading that templates were slower I'm looking at going with recursive binding.

<ul data-bind="nestMe: name"></ul>

ko.bindingHandlers.nestMe = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {

    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var observable = valueAccessor() || { };
        var unwrapped = ko.unwrap(observable);

        ko.utils.setHtml(element, '<li>'+unwrapped+'<ul data-bind="foreach: children"><li data-bind="nestMe: name" /></ul></li>');


var rootModel = function(name, children) { = ko.observable(name);
    this.children = ko.observableArray(children);

var basemodel = new rootModel('test');
basemodel.children.push(new rootModel('aaa',[new rootModel('111'),new rootModel('222')]));
basemodel.children.push(new rootModel('bbb'));
basemodel.children.push(new rootModel('ccc',[new rootModel('333'),new rootModel('444')]));


Having the opportunity to play with data before the recursion should come in handy.


Need Your Help

detect eap pakets (802.1X auth) with pcap libraries

c protocols pcap packet-sniffers

i'm writing a c sniffer with pcap (on my own recorded .cap streams).

how to define friendly URL for PrestaShop non-core pages


The friendly URLs are stored in the database for all the pages where they are used, but how would I define a friendly URL for this page: