[AngularJS] Treeview


Treeview via AngularJS.

Demo

Real world application of treeview is Pāli Tipiṭaka.

Source code:

index.html | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!doctype html>
<html ng-app="demoTreeview">
<head>
  <meta charset="utf-8">
  <title>AngularJS Treeview Demo</title>
  <link rel="stylesheet" type="text/css" href="treeview.css">
</head>
<body>

<div treeview></div>

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script src="treeviewData.js"></script>
<script src="treeview.js"></script>
<script src="app.js"></script>
</body>
</html>
app.js | repository | view raw
1
2
3
4
5
6
7
'use strict';


angular.module('demoTreeview', ['treeview', "treeviewData"]).
  run([function() {
    // nothing to initialize
  }]);
treeview.js | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
'use strict';

/* Directives */


angular.module('treeview', []).
  directive('treeview', ['$compile', 'treeviewData', function($compile, treeviewData) {
    return {
      restrict: 'A',
      link: function(scope, elm, attrs) {

        // show items
        for (var i=0; i< treeviewData.all['child'].length; i++) {
          var node = traverseTreeviewData( treeviewData.all['child'][i]);
          elm.append(node);
        }

        function traverseTreeviewData(node) {
          var text = node['text'];
          if (node['child']) {
            // not leaf node, keys: 'text', 'child'
            var element = angular.element('<div class="item"></div>');
            var sign = angular.element('<span>+</span>');
            var textElm = $compile(
                '<span class="treeNode">'+ text + '</span>'
                )(scope);

            element.append(sign);
            element.append(textElm);

            var childrenContainer = $compile('<div class="childrenContainer"></div>')(scope);
            for (var i=0; i<node['child'].length; i++) {
              var child = node['child'][i];
              childrenContainer.append(traverseTreeviewData(child));
            }
            childrenContainer.css('display', 'none');

            textElm.bind('click', function() {
              if (childrenContainer.css('display') === 'none') {
                childrenContainer.css('display', '');
                sign.html('-');
              } else {
                childrenContainer.css('display', 'none');
                sign.html('+');
              }
            });

            var all = angular.element('<div></div>');
            all.append(element);
            all.append(childrenContainer);
            return all;
          } else {
            // leaf node, keys: 'text'
            var element = $compile(
                '<div class="item"><span class="treeNode">' + text + '</span></div>'
                )(scope);

            return element;
          }
        }
      }
    };
  }]);
treeviewData.js | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
angular.module('treeviewData', []).
  factory('treeviewData', [function() {
    var data = {"child": [
      { "text": "item 1",
        "child": [
          { "text": "item 1-1" },
          { "text": "item 1-2",
            "child": [
              { "text": "item 1-2-1" },
              { "text": "item 1-2-2" }
            ]},
          { "text": "item 1-3" }
        ]},
      { "text": "item 2",
        "child": [
          { "text": "item 2-1" },
          { "text": "item 2-2" }
        ]},
      { "text": "item 3" }
    ]}
    var serviceInstance = { all: data };
    return serviceInstance;
  }]);
treeview.css | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
.item {
  margin-bottom: 3px;
  padding-bottom: 3px;
  border-bottom: 1px solid #E0E0E0;
}

.item:hover {
  background-color: #F0F8FF;
}

.treeNode:hover {
  cursor: pointer;
  color: blue;
}

.childrenContainer {
  margin-left: .4em;
  padding-left: .4em;
  border-left: 1px dotted blue;
}

Tested on: Chromium Version 50.0.2661.102 Ubuntu 16.04 (64-bit), AngularJS 1.5.5.


References:

[1]