Interview Questions

Recursive Templates in Underscore Js

Use the following code to call a template recursively in Underscore JS.
This example use Backbone JS, JSTree(Jquery) to display tree nodes

<!DOCTYPE html>
<html lang="en">
        <head>
                <meta charset="utf-8">
                <title>Tree Structure</title>
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <meta name="description" content="">
                <meta name="author" content="">
                <!-- Le styles -->
                <link href="css/bootstrap.css" rel="stylesheet">
                <link href="css/bootstrap-responsive.css" rel="stylesheet">
                <link href="css/style.css" rel="stylesheet">
                <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements --><!--[if lt IE 9]> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--><!-- Le fav and touch icons -->
                <link rel="shortcut icon" href="assets/ico/favicon.ico">
                <link rel="apple-touch-icon-precomposed" sizes="144x144" href="pages/ico/apple-touch-icon-144-precomposed.png">
                <link rel="apple-touch-icon-precomposed" sizes="114x114" href="pages/ico/apple-touch-icon-114-precomposed.png">
                <link rel="apple-touch-icon-precomposed" sizes="72x72" href="pages/ico/apple-touch-icon-72-precomposed.png">
                <link rel="apple-touch-icon-precomposed" href="pages/ico/apple-touch-icon-57-precomposed.png">
        </head>

        <body>
                <script src="js/jquery.js"></script>
                <script src="js/jquery.jstree.js"></script>
                <script src="js/underscore.js"></script>
                <script src="js/backbone.js"></script>
                <script src="js/bootstrap.js"></script>
                <script src="js/jstorage.js"></script>

                <script type="text/javascript">
                        $(document).ready(function() {

                                var departments = new Array();
                                var subDepartments = new Array();
                                var subAdminDepartments = new Array();
                                var Employee = Backbone.Model.extend({});
                                var Department = Backbone.Model.extend({
                                        defaults : {
                                                employees : [],
                                                departments : []
                                        }

                                });

                                var dept1 = new Department({
                                        name : "Finanace"
                                });
                                var dept2 = new Department({
                                        name : "HR"
                                });
                                var dept3 = new Department({
                                        name : "IT"
                                });
                                var dept4 = new Department({
                                        name : "Admin"
                                });

                                var dept5 = new Department({
                                        name : "ACCOUNTS",
                                        departments : []
                                });
                                subDepartments.push(dept5);
                                var dept6 = new Department({
                                        name : "QA",
                                        departments : []
                                });
                                subDepartments.push(dept6);
               
                subAdminDepartments.push(dept2);
                subAdminDepartments.push(dept3);
               
                                dept1.set({
                                        departments : subDepartments
                                });
                                dept4.set({
                                        departments : subAdminDepartments
                                });

                                departments.push(dept1);
                                departments.push(dept4);

                                var TreeView = Backbone.View.extend({
                                        el : "#treeViewDiv",
                                        tagName : "div",
                                        className : "",

                                        currentTemplate : $("#treeTemplate").html(),

                                        events : {

                                        },

                                        render : function() {
                                                //var data = this.model.toJSON();
                                                var childTemplate = _.template($("#treeChildTemplate").html());
                                                var tmpl = _.template(this.currentTemplate);

                                                this.$el.html(tmpl({
                                                        "departments" : departments,
                                                        "templateFn" : childTemplate
                                                }));

                                                return this;
                                        },
                                });

                                function populateTree() {

                                        var tree_reference = $("#treeViewDiv").jstree({
                                                "themes" : {
                                                        "theme" : "classic"
                                                },
                                                "plugins" : ["themes", "html_data", "ui"],
                                                "ui" : {
                                                        "initially_select" : ['']
                                                }
                                        });
                                }

                                var treeView = new TreeView();
                                treeView.render();

                                populateTree();

                        });
                </script>
                <script id="treeTemplate" type="text/template">

                        <div class="content span-7" id="treeViewDiv">
                        <ul id="tree">
                        <% _.each(departments, function (node) {

                        node = node.toJSON();
                        %>

                        <% if (node.name != null) { %>
                        <%= node.name %> &nbsp;
                        <% } %>

                        <%= templateFn({"model":node, "departments": node.departments, "templateFn": templateFn }) %>

                        <% }); %>

                        </ul>
                        </div>

                </script>

                <script id="treeChildTemplate" type="text/template">

                        <% if (departments != null && departments.length > 0) {         %>
                        <li ><span id="<%= model.id %>" class="" href="#"> &nbsp; <%= model.name %></span>
                        <ul >

                        <% _.each(departments, function (item) {

                        item = item.toJSON();
                        %>

                        <%= templateFn({"model":item, "departments": item.departments, "templateFn": templateFn }) %>

                        <% }); %>

                        </ul>

                        <% }  else {    %>

                        <li ><span id="<%= model.id %>" class="" href="#"> &nbsp; <%= model.name %></span></li>

                        <% } %>

                </script>
                <div id="treeViewDiv"></div>

        </body>
</html>

Note: Please include the necessary js frameworks such as underscore.js, backbone.js, jquery.js,jquery.jstree.js for the above example to work.