0

I wrote an angularjs service, which uses function shown below to generate tree-like array from "flat" one. This service is injected as a dependency for a controller(see below) and bound to scope via get() method returned in service object.

var arr = [
  {"id": 1, "firstName": "Macko","parentId": 12},
  {"id": 2, "firstName": "Jess","parentId": 1},
  {"id": 3, "firstName": "Peter","parentId": 1},
  {"id": 4, "firstName": "Lisa", "parentId": 1},
  {"id": 5, "firstName": "Megan","parentId": 1},
  {"id": 6, "firstName": "John", "parentId": 4},
  {"id": 7, "firstName": "Joe", "parentId": 4},
  {"id": 8, "firstName": "Matthew","parentId": 2},
  {"id": 9, "firstName": "Peter","parentId": 2},
  {"id": 10, "firstName": "Dio","parentId": 5},
  {"id": 11, "firstName": "Hello","parentId": 5},
  {"id": 12, "firstName": "Ana", "parentId": 4}
];

var getNestedChildren = function(arr, id, checked) {

  var out = [];
  for (var i = 0; i < arr.length; i++) {
    if (arr[i].parentId === id && checked.indexOf(arr[i].id) === -1) {
      checked.push(id);
      var children = getNestedChildren(arr, arr[i].id, checked);
      if (children.length) {
        arr[i].children = children;
      }
      out.push(arr[i]);
    }
  }
  return out;

};

return {

       get: function (element) {
            return getNestedChildren(arr, element.id, []);
       }

}

I bind this tree to $scope in controller like below. Parameter for generating tree is passed in URL.

$scope.tree = myService.get({elementId: $routeParams.elementId});

When I switch routes few times to see trees for different parameters, created tree has more elements each time, until at some point angular returns error

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting! 

My guess is, because myService is a singleton it retains state through routes and that why I get inconsistent data.

How can I stop this behaviour? Maybe reset service after it generated particular tree?

Please help.

EDIT: I tried cleaning $templateCache and $scope while leaving particular view, but without effect. As of now, only browser refresh show correct tree after switching few routes.

As per request showing html that renders tree:

Directive

angular.module('app').directive('showTree', [function () {

        return {
            restrict: 'E',
            templateUrl: 'app/tree/tree.tpl.html'
        }

    }]);

tree.tpl.html:

<h3> {{selectedElement.firstName}} {{selectedElement.lastName}}"></h3>
<ul>
    <li ng-repeat="element in tree" ng-include="'tree'"></li>
</ul>

<script type="text/ng-template" id="tree">
    <h3> {{element.firstName}} {{element.lastName}}"></h3>
    <ul>
        <li ng-repeat="element in element.children" ng-include="'tree'"></li>
    </ul>
</script>

Controller

angular.module('app')
        .controller('TreeController', ['$scope', '$routeParams', 'ElementFactory', 'myService',
            function ($scope, $routeParams, ElementFactory, myService) {

                $scope.selectedElement = ElementFactory.get({elementId: $routeParams.elementId});

                $scope.tree = myService.get({elementId: $routeParams.elementId});

            }]);
Ketus
  • 123
  • 1
  • 11

1 Answers1

0

10 digest loops means that you made angulars detecting changes for 10 times in a row on the successive angular's loop.

Furthermore i don't see anything that make think that your service is retaining any states.

I think you have something wrong in your tree indeed, but not with what you posted here. Show us your HTML showing the tree and the controlleralong with it.

Walfrat
  • 5,363
  • 1
  • 16
  • 35
  • I think i found it remove line of id 12 and tell me if it happens again, you have a cycle in your tree. `12 <- 1 <- 4 <- 12` – Walfrat Apr 18 '16 at 15:03
  • It won't but it has to be there. It's circular reference tree, and recursive function stops generating tree before it finds same id that it started with. – Ketus Apr 18 '16 at 15:05
  • Hum too many level maybe ? Try first without circular but just with 4 or 5 levels. Pur angular doesn't always fit for everything. Maybe develop your own directive that use some jQuery tree or whatever component behind the scene would work better. – Walfrat Apr 18 '16 at 15:09
  • It works fine when not dealing with circular reference. Interesting thing is that if I refresh page while on view that was rendered incorrectly, it re-renders properly. – Ketus Apr 18 '16 at 15:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/109454/discussion-between-ketus-and-walfrat). – Ketus Apr 18 '16 at 15:16
  • Without console errors, and with proper amount of elements. – Ketus Apr 18 '16 at 15:17