How to deal with browser freezing because of nested ng-repeat : <p>I created a nested tree which may have 1 - 5000 items, I am able to make it work but it freezes my browser\loading spinner for few seconds just before showing the tree.</p>

<p><strong><em>How can I make it smooth so browser would never freeze ?</em></strong></p>

<p><strong><em>How can I know when angularjs finished creating or rendering or computing (not sure right word) whole list so that I could remove loading spinner then, as you can see scope.$last won't work as we have nested ng-repeat and same for scope.$parent.$last</em></strong> </p>

<p>Here is plunker I created but with demo data - </p>

<p><a href="http://plnkr.co/edit/GSZEpHjt5YVxqpg386k5?p=preview" rel="noreferrer">http://plnkr.co/edit/GSZEpHjt5YVxqpg386k5?p=preview</a></p>

<p>Example dataset - <a href="http://pastebin.com/YggqE2MK" rel="noreferrer">http://pastebin.com/YggqE2MK</a></p>

<p>It's not too bad in this example but at points my browser freezes for more then 10 seconds for around 4000 items in my OWN setup with all other components.</p>

<p><strong>What I already considered</strong></p>

<ul>
<li>used bindonce.js library but without much success</li>
<li>used "::" single binding without much success again</li>
<li>only load first level then render next level when user expands a category but my tree can be very random, maybe I only have 1 single root node with 100s child nodes</li>
<li>pagination is not ideal for scenario</li>
</ul>

<p><strong>HTML</strong></p>

<pre><code>  &lt;script type="text/ng-template" id="tree_item"&gt;
    &lt;div ng-init="category.expanded=true"&gt;
      &lt;div ng-class="{'selected': category.ID==selectedCategoryID}"&gt;
        &lt;div class="icon icon16" ng-if="category.Children.length&gt;0" ng-click="$parent.category.expanded=!$parent.category.expanded" ng-class="$parent.category.expanded?'col':'exp'"&gt;&lt;/div&gt;
        &lt;div class="icon icon-category" ng-class="'icon-category-'+category.TypeType" ng-style="{'border-color':category.Colour}" ng-attr-title="{{category.Status?Res['wpOPT_Status'+category.Status]:''}}"&gt;&lt;/div&gt;
        &lt;a ng-href="#id={{category.ID}}" ng-class="{'pending-text': category.PendingChange}"&gt;{{category.Name}}&lt;/a&gt;
      &lt;/div&gt;
      &lt;ul class="emlist" ng-show="category.expanded"&gt;
        &lt;li ng-repeat="category in category.Children | orderBy:'Name'" ng-include="'tree_item'" ng-class="{'selected': category.ID==selectedCategoryID}" e2-tree-item is-selected="category.ID==selectedCategoryID"&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/script&gt;

  &lt;div id="CategoryListContainer" class="dragmenu-container initial-el-height"&gt;
    &lt;div class="spinner" data-ng-show="status=='loading'"&gt;&lt;/div&gt;
    &lt;ul id="CategoryList" class="dragmenu-list ng-cloak" ng-show="status=='loaded'"&gt;
      &lt;li ng-repeat="category in tree | orderBy:'Name'" ng-include="'tree_item'" e2-tree-item is-selected="category.ID==selectedCategoryID"&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
</code></pre>

<p><strong>JS</strong></p>

<pre><code>var app = angular.module('recursionDemo', []);

app.controller("TreeController", function($scope, $timeout) {
  $scope.status = "loading";

  $timeout(function() {
        var result = {
      "GetCategoryTreeResult": [{ // too big data set so I pasted it here http://pastebin.com/YggqE2MK }];
    $scope.tree = result.GetCategoryTreeResult;

    $scope.status = "loaded";
  }, 3000);
});

app.directive('e2TreeItem', function($timeout) {
  function link(scope, element, ngModel) {
    scope.$watch('isSelected', function(oldVal, newVal) {
      if (scope.isSelected === true) {
        element.parentsUntil('#CategoryListContainer', 'li').each(function(index, item) {
          angular.element(item).scope().category.expanded = true;
        });
      }
    });

    // not working
    //if (scope.$parent.$last) {
    //  console.log("last has been caught");
    //  var appElement = document.querySelector('[ng-app=recursionDemo]');
    //  angular.element(appElement).scope().status = "loaded";
    //}
  }
  return {
    link: link,
    scope: {
      isSelected: '=?'
    }
  };
});
</code></pre>
