Tree View control with JavaScript and Knockout for large trees

[To understand this post, get the code from git]

Few days back, I needed  a Tree View, which should be able to show tree with thousands of nodes, a big tree, a really very big tree.

Most of the existing tree views used to crash my browser, they are making the naive mistake to load all the nodes in one shot. The simple solution was to load the nodes on demand, and when you open a node with thousands of children, and then you open another node which again has thousands of children, it is better to close the previous node and let go all their children than crash the browser.

Now, this tree automatic closing the previous node can have little more intelligent, and not necessarily close the node if the number of its children is small. So this tree is little intelligent in few aspect, it loads the children on demand, closes and flushes the nodes which creates the danger of crashing the browser. This tree trade performance over reliability.

To build a tree with JavaScript and  Knockout, you need to understand how knockout templeting works. The template binding populates the associated DOM element with the results of rendering a template. Templates are a simple and convenient way to build sophisticated UI structures. String-based templating is a way to connect Knockout to a third-party template engine. Knockout will pass your model values to the external template engine and inject the resulting markup string into your document.

If you don’t know about KO templating, then you should stop here and read more about it here.

To create a new string template engine, start with an existing nativeTemplateEngine.

CreateStringTemplateEngine method does that task.

SetEngine() {
         this.customTemplateEngine = TreeTempate.createStringTemplateEngine(
                new ko.nativeTemplateEngine(), this.templates);
        ko.setTemplateEngine(this.customTemplateEngine);
}

Inside createStringTemplateEngine, we use passed templateEngine and override it’s makeTemplateSource function to returns our stringTemplate, as follows:

     templateEngine.makeTemplateSource = function (templateName) {
           return new stringTemplate(templateName, templates);
    }

So again, take a nativeTemplateEngine of ko, and override it’s makeTemplateSource and return your own stringTemplate. This makeTemplateSource method is called from ko.renderTemplate function, which in turn calls your template “text” method.

Here is how template engine is implemented, you just have to implement one methods ‘text’:

class stringTemplate {

private _templateName: string;
private _templates: any;

constructor (templateName, templates) {
    this._templateName = templateName;
    this._templates = templates;
}
text (value) {
    if (arguments.length === 0) {
        return this._templates[this._templateName];
    }
    this[this._templateName] = value;
}
};

Templates is defined as follows:

knockoutTemplate

Pay close attention to how templates are recursively calling each other to draw the tree. First template (tree) calls nodes and nodes calls nodeCore to draw the real node. NodeCore has two calls one is to subNodes, and the other one is to nodeContent. Writing this recursive template is key to drawing your tree on the browser.

KO will call stringTemplate, text method again and again with the template names it keep encountering and we will keep returning their value e.g, for ‘tree’ text will return ”

The html of the page is as simple as this:

<html>
    <body>
       <div data-bind="template: { name: TreeTemplate }"  />
    </body>
</html>

<script>
 $(document).ready(function () {
        var d = new data.Data();
        var vm = new Tree.viewModel(d);
        ko.applyBindings(vm);
 });
</script>

This is how the tree will look.
TreeChild

When the Ko hit the following html  data-bind=”template: { name: TreeTemplate }”  It start processing the ‘tree’ template in templates. Which says for each item, please apply the node template. And then node template says for data apply the nodeCore template, and this templating continues on till we reach to nodeContent.

Rest of the code deals with clicking on nodes and loading children on demand, checking the status of tree, and automatically closing nodes which are too big and pose a threat to crash the browser. These cut-off number are configurable in the code, and you should be able to change and play with it. Interesting part of the code is many of the recursive functions. These functions need to traverse down thru the child nodes before they close a parent node.

Hopefully, this will get started you on your journey of creating a TreeView with KO and JavaScript.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s