Wijmo 5 - Lazy-Loaded Tree

HTML

<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="http://cdn.wijmo.com/5.20143.35/controls/wijmo.min.js"></script>
<link rel="stylesheet" href="http://cdn.wijmo.com/5.20143.35/styles/wijmo.min.css">
<script src="http://cdn.wijmo.com/5.20143.35/controls/wijmo.grid.min.js"></script>
<script src="http://cdn.wijmo.com/5.20143.35/interop/angular/wijmo.angular.min.js"></script>
<!-- mark this as an Angular application and give it a controller -->
<div ng-app="app" ng-controller="appCtrl">
    
    <h3>Lazy-loaded tree</h3>
    
    <p>
        In the tree below, closed nodes have a single
        dummy child. When a node is expanded, more nodes
        are loaded on demand.</p>

    <wj-flex-grid 
        items-source="tree"
        child-items-path="children"
        initialized="initTree(s,e)"
        group-collapsed-changed="groupCollapsedChanged(s,e)">
        <wj-flex-grid-column binding="name" width="*"></wj-flex-grid-column>
        <wj-flex-grid-column binding="id"></wj-flex-grid-column>
    </wj-flex-grid>
</div>

CSS

.wj-flexgrid .wj-group {
    background-color: white;
}

JavaScript

// define app, include Wijmo 5 directives
var app = angular.module('app', ['wj']);

// controller
app.controller('appCtrl', function ($scope) {

    // create tree for lazy-loading example
    var tree = [], nodeId = 0;
    tree.push(createNode());
    tree.push(createNode());
    function createNode(dummy) {
        var first = 'Al,Bob,Cal,Dan,Ed,Fred,Greg,Hal,Ian,Jack,Karl,Lou,Moe,Nate,Oleg,Paul,Quincy,Rod,Sue,Uwe,Vic,Walt,Xiu,Yuri,Zack'.split(','),
            last = 'Adams,Baum,Cole,Dell,Evans,Fell,Green,Hill,Isman,Jones,Krup,Lee,Monk,Nye,Opus,Pitt,Quaid,Riems,Stark,Trell,Unger,Voss,Wang,Xie,Zalm'.split(','),
            r1 = Math.round(Math.random() * 10000),
            r2 = Math.round(Math.random() * 10000),
            name = dummy ? '' : first[r1 % first.length] + ' ' + last[r2 % last.length],
            children = [];
        if (!dummy) {
            children.push(createNode(true));
        }
        return { id: nodeId++, name: name, children: children };
    }

    // expose tree to scope
    $scope.tree = tree;

    // start collapsed
    $scope.initTree = function (s, e) {
        s.collapseGroupsToLevel(0);
        s.formatItem.addHandler(function(s, e) {
            if (s.columns[e.col].binding == 'id') {
                e.cell.innerHTML = '<i>' + e.panel.getCellData(e.row, e.col, true) + '</i>';
            }
        });
    }

    // lazy load items when opening nodes with a dummy child
    $scope.groupCollapsedChanged = function (s, e) {
        var row = s.rows[e.row],
            item = row.dataItem;

        // did we just expand a node with a dummy child?
        if (!row.isCollapsed && item.children.length == 1 && item.children[0].name == '') {

            // can't lazy load while updating rows
            if (s.rows.isUpdating) {
                row.isCollapsed = true;
                return;
            }
            
            // save collapsed state
            var collapsed = [];
            for (var i = 0; i < s.rows.length;...