Angular: Treeview example as directive

A simple treeview implemented with angular and ngInclude

by Richard Houltz

HTML

<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<div ng-app="Application" ng-controller="TreeController">
    <h1>Treeview</h1>
    <treeview root="root"></treeview>
    <hr/>
    <h1>Data:</h1>
    <pre>{{root | json}}</pre>  
</div>

<script type="text/ng-template" id="tree_item.html">
    <span ng-click="data.$expanded = !data.$expanded">
        <span ng-show="data.nodes.length == 0" class="glyphicon glyphicon-record"></span>
        <span ng-show="data.nodes.length > 0 && !data.$expanded" class="glyphicon glyphicon-folder-close"></span>
        <span ng-show="data.nodes.length > 0 && data.$expanded > 0" class="glyphicon glyphicon-folder-open"></span>
        {{data.name}} <span class="badge">{{data.nodes.length}}</span>
    </span>
    <button ng-click="add(data)" class="btn btn-primary btn-xs">Add child</button>
    <button ng-click="delete(data)" ng-show="data.$parent" class="btn btn-danger btn-xs">Remove</button>

    <ul ng-if="data.$expanded" class="list-unstyled">
        <li ng-repeat="data in data.nodes" ng-include="'tree_item.html'"></li>
    </ul>
</script>

CSS

li {
    margin-left: 15px;
    margin-top: 10px
}

JavaScript

var myApp = angular.module('myApp', [])

    .directive('treeview', function () {
    return {
        restrict: 'E',
        scope: {
            data: '=root'
        },
        controller: function ($scope) {
            $scope.delete = function (data) {
                var index = data.$parent.nodes.indexOf(data);
                data.$parent.nodes.splice(index, 1);
            };

            $scope.add = function (data) {
                var newName = data.name + '-' + (data.nodes.length + 1);
                data.nodes.push({
                    name: newName,
                    nodes: [],
                    $expanded: true,
                    $parent: data
                });
            };

            if (!$scope.data.nodes) $scope.data.nodes = [];

            $scope.data.$expanded = true;
        },
        templateUrl: 'tree_item.html'
    };
})

    .controller("TreeController", ['$scope', function ($scope) {
    $scope.root = {
        name: 'Node'
    };
}]);