<div ng-app="myApp">
  <div ng-controller="myController">

    <div>
      <input type="button" value="TREE MODEL 1" data-ng-click="roleList = roleList1" /> <input type="button" value="TREE MODEL 2" data-ng-click="roleList = roleList2" />
    </div>

    <div style="margin:10px 0 30px 0; padding:10px; background-color:#EEEEEE; border-radius:5px; font:12px Tahoma;">
      <span><b>Selected Node</b> : {{mytree.currentNode.roleName}}</span>
    </div>

    <!--
      [TREE attribute]
      angular-treeview: the treeview directive
      tree-id : each tree's unique id.
      tree-model : the tree model on $scope.
      node-id : each node's id
      node-label : each node's label
      node-children: each node's children
    -->
    <div
      data-angular-treeview="true"
      data-tree-id="mytree"
      data-tree-model="roleList"
      data-node-id="roleId"
      data-node-label="roleName"
      data-node-children="children" >
    </div>

  </div>
</div>
div[data-angular-treeview] {
  /* prevent user selection */
  -moz-user-select: -moz-none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;

  /* default */
  font-family: Tahoma;
  font-size:13px;
  color: #555;
  text-decoration: none;
}

div[data-tree-model] ul {
  margin: 0;
  padding: 0;
  list-style: none; 
  border: none;
  overflow: hidden;
}

div[data-tree-model] li {
  position: relative;
  padding: 0 0 0 20px;
  line-height: 20px;
}

div[data-tree-model] li .expanded {
  padding: 1px 10px;
  background-image: url("http://cfile23.uf.tistory.com/image/205B973A50C13F4B19D9BD");
  background-repeat: no-repeat;
}

div[data-tree-model] li .collapsed {
  padding: 1px 10px;
  background-image: url("http://cfile23.uf.tistory.com/image/1459193A50C13F4B1B05FB");
  background-repeat: no-repeat;
}

div[data-tree-model] li .normal {
  padding: 1px 10px;
  background-image: url("http://cfile23.uf.tistory.com/image/165B663A50C13F4B196CCA");
  background-repeat: no-repeat;
}

div[data-tree-model] li i, div[data-tree-model] li span {
  cursor: pointer;
}

div[data-tree-model] li .selected {
  background-color: #aaddff;
  font-weight: bold;
  padding: 1px 5px;
}
(function(){
  
  //angular module
  var myApp = angular.module('myApp', ['angularTreeview']);

  //test controller
  myApp.controller('myController', function($scope){

  	//test tree model 1
    $scope.roleList1 = [
        { "roleName" : "User", "roleId" : "role1", "children" : [
          { "roleName" : "subUser1", "roleId" : "role11", "children" : [] },
          { "roleName" : "subUser2", "roleId" : "role12", "children" : [
            { "roleName" : "subUser2-1", "roleId" : "role121", "children" : [
              { "roleName" : "subUser2-1-1", "roleId" : "role1211", "children" : [] },
              { "roleName" : "subUser2-1-2", "roleId" : "role1212", "children" : [] }
            ]}
          ]}
        ]},

        { "roleName" : "Admin", "roleId" : "role2", "children" : [] },

        { "roleName" : "Guest", "roleId" : "role3", "children" : [] }
      ];

  	//test tree model 2
    $scope.roleList2 = [
        { "roleName" : "User", "roleId" : "role1", "children" : [
          { "roleName" : "subUser1", "roleId" : "role11", "collapsed" : true, "children" : [] },
          { "roleName" : "subUser2", "roleId" : "role12", "collapsed" : true, "children" : [
            { "roleName" : "subUser2-1", "roleId" : "role121", "children" : [
              { "roleName" : "subUser2-1-1", "roleId" : "role1211", "children" : [] },
              { "roleName" : "subUser2-1-2", "roleId" : "role1212", "children" : [] }
            ]}
          ]}
        ]},

        { "roleName" : "Admin", "roleId" : "role2", "children" : [
          { "roleName" : "subAdmin1", "roleId" : "role11", "collapsed" : true, "children" : [] },
          { "roleName" : "subAdmin2", "roleId" : "role12", "children" : [
            { "roleName" : "subAdmin2-1", "roleId" : "role121", "children" : [
              { "roleName" : "subAdmin2-1-1", "roleId" : "role1211", "children" : [] },
              { "roleName" : "subAdmin2-1-2", "roleId" : "role1212", "children" : [] }
            ]}
          ]}
        ]},

        { "roleName" : "Guest", "roleId" : "role3", "children" : [
          { "roleName" : "subGuest1", "roleId" : "role11", "children" : [] },
          { "roleName" : "subGuest2", "roleId" : "role12", "collapsed" : true, "children" : [
            { "roleName" : "subGuest2-1", "roleId" : "role121", "children" : [
              { "roleName" : "subGuest2-1-1", "roleId" : "role1211", "children" : [] },
              { "roleName" : "subGuest2-1-2", "roleId" : "role1212", "children" : [] }
            ]}
          ]}
        ]}
      ];

      
      
    //roleList1 to treeview
    $scope.roleList = $scope.roleList1;
  
  });
  
})();


/*
        @license Angular Treeview version 0.1.6
        ⓒ 2013 AHN JAE-HA https://github.com/eu81273/angular.treeview
        License: MIT


        [TREE attribute]
        angular-treeview: the treeview directive
        tree-id : each tree's unique id.
        tree-model : the tree model on $scope.
        node-id : each node's id
        node-label : each node's label
        node-children: each node's children

        <div
                data-angular-treeview="true"
                data-tree-id="tree"
                data-tree-model="roleList"
                data-node-id="roleId"
                data-node-label="roleName"
                data-node-children="children" >
        </div>
*/

(function ( angular ) {
        'use strict';

        angular.module( 'angularTreeview', [] ).directive( 'treeModel', ['$compile', function( $compile ) {
                return {
                        restrict: 'A',
                        link: function ( scope, element, attrs ) {
                                //tree id
                                var treeId = attrs.treeId;
                        
                                //tree model
                                var treeModel = attrs.treeModel;

                                //node id
                                var nodeId = attrs.nodeId || 'id';

                                //node label
                                var nodeLabel = attrs.nodeLabel || 'label';

                                //children
                                var nodeChildren = attrs.nodeChildren || 'children';

                                //tree template
                                var template =
                                        '<ul>' +
                                                '<li data-ng-repeat="node in ' + treeModel + '">' +
                                                        '<i class="collapsed" data-ng-show="node.' + nodeChildren + '.length && node.collapsed" data-ng-click="' + treeId + '.selectNodeHead(node)"></i>' +
                                                        '<i class="expanded" data-ng-show="node.' + nodeChildren + '.length && !node.collapsed" data-ng-click="' + treeId + '.selectNodeHead(node)"></i>' +
                                                        '<i class="normal" data-ng-hide="node.' + nodeChildren + '.length"></i> ' +
                                                        '<span data-ng-class="node.selected" data-ng-click="' + treeId + '.selectNodeLabel(node)">{{node.' + nodeLabel + '}}</span>' +
                                                        '<div data-ng-hide="node.collapsed" data-tree-id="' + treeId + '" data-tree-model="node.' + nodeChildren + '" data-node-id=' + nodeId + ' data-node-label=' + nodeLabel + ' data-node-children=' + nodeChildren + '></div>' +
                                                '</li>' +
                                        '</ul>';


                                //check tree id, tree model
                                if( treeId && treeModel ) {

                                        //root node
                                        if( attrs.angularTreeview ) {
                                        
                                                //create tree object if not exists
                                                scope[treeId] = scope[treeId] || {};

                                                //if node head clicks,
                                                scope[treeId].selectNodeHead = scope[treeId].selectNodeHead || function( selectedNode ){

                                                        //Collapse or Expand
                                                        selectedNode.collapsed = !selectedNode.collapsed;
                                                };

                                                //if node label clicks,
                                                scope[treeId].selectNodeLabel = scope[treeId].selectNodeLabel || function( selectedNode ){

                                                        //remove highlight from previous node
                                                        if( scope[treeId].currentNode && scope[treeId].currentNode.selected ) {
                                                                scope[treeId].currentNode.selected = undefined;
                                                        }

                                                        //set highlight to selected node
                                                        selectedNode.selected = 'selected';

                                                        //set currentNode
                                                        scope[treeId].currentNode = selectedNode;
                                                };
                                        }

                                        //Rendering template.
                                        element.html('').append( $compile( template )( scope ) );
                                }
                        }
                };
        }]);
})( angular );
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.7/angular.min.js