<!DOCTYPE html>
<html ng-app="tree">

  <head>
    <link data-require="bootstrap-css@*" data-semver="3.0.2" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/2.3.2/css/bootstrap.min.css" />
    <link data-require="font-awesome@3.2.1" data-semver="3.2.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css" />
    <script data-require="angular.js@1.0.8" data-semver="1.0.8" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
    <script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script data-require="bootstrap@2.3.2" data-semver="2.3.2" src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
    <script data-require="lodash.js@2.3.0" data-semver="2.3.0" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div ng-controller="TreeController">
      <h2 ng-bind="title" class="alert alert-success"></h2>
      <ul class="tree-container">
        <li style="margin: 5px; list-style: none;" ng-repeat="d in getChildren()" ng-include="'tree_item_renderer.html'"></li>
      </ul>
      
    </div>
  </body>


<script type="text/ng-template"  id="tree_item_renderer.html">
    
    <i ng-show="!d.$expand && hasChildren(d.id)" class="icon-plus" ng-click="d.$expand = !d.$expand"></i> 
    <i ng-show="d.$expand && hasChildren(d.id)" class="icon-minus" ng-click="d.$expand = !d.$expand"></i>
    <span ng-show="!hasChildren(d.id)" style="margin-left:16px"></span>
    {{d.label}}
    <ul>
        <li style="list-style:none;"  ng-repeat="d in getChildren(d.id)" ng-include="'tree_item_renderer.html'"></li>
    </ul>
</script>
</html>
// Code goes here

angular.module('tree', [])

.controller('TreeController', function($scope) {
  $scope.title = "Tree";
  
  $scope.data = [
    {id: '1', label: 'root', parentId: 'null', $expand: true},
    {id: '2', label: 'child 11', parentId: '1', $expand: false},
    {id: '3', label: 'child 12', parentId: '1', $expand: false},
    {id: '4', label: 'child 13', parentId: '1', $expand: false},
    {id: '5', label: 'child 14', parentId: '1', $expand: false},
    {id: '6', label: 'child 111', parentId: '2', $expand: false},
    {id: '7', label: 'child 1111', parentId: '6', $expand: false},
    {id: '8', label: 'child 121', parentId: '3', $expand: false},
    {id: '9', label: 'child 122', parentId: '3', $expand: false},
    {id: '9', label: 'child 131', parentId: '4', $expand: false}
  ];
  
  $scope.getChildren = function(parentId) {
    if(!parentId) {
      return [$scope.data[0]];
    }
    
    if(!_($scope.data).where({id: parentId}).value()[0]['$expand']) {
      return [];
    }
    return _($scope.data).where({parentId: parentId}).value();
  }
  
  $scope.hasChildren = function(id) {
    if(!id) {
      return (_($scope.data).where({parentId: $scope.data[0].id}).value().length !== 0);
    }
    
    return (_($scope.data).where({parentId: id}).value().length !== 0);
  }
});
/* Styles go here */

.tree-container {
  height: 100%;
  color: #444;
  font-weight: 200;
}

i {
  cursor: pointer;
}