<!DOCTYPE html>
<html ng-app="angularjs-starter">
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
<link rel="stylesheet" href="style.css">
<script>
document.write('<base href="' + document.location + '" />');
</script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<ng-form>
<input ng-model="node.name">
<button ng-click="createNode(node.name)">create</button>
</ng-form>
<ul tree roots="nodes" item="n">
<li draggable="true" ng-init="collapsed=false">
<div class="node" ng-style="{'padding-left':(20*level)+'px'}">
<button ng-click="collapsed=!collapsed">+</button>
{{n.name}}
</div>
<div ng-show="!collapsed"><recur></recur></div>
</li>
</ul>
</body>
</html>
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.nodes = [
{name: "Foo", children: [{name: "Bar", children: []}]},
{name: "Lorem", children: [
{name: "Ipsum", children: [{name: "Dolor", children: []}]}]},
{name: "Quux", children: []}
];
$scope.createNode = function(name) {
$scope.nodes.push({name: name, children: []});
};
});
app.directive('tree', function() {
function linker(parent) {
return function(clone) {
parent.append(clone);
};
}
function buildTree(parNode, level, nodes, scope, ident, transclude) {
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
var nodeScope = scope.$new();
nodeScope[ident] = node;
nodeScope.level = level;
transclude(nodeScope, linker(parNode));
if (node.children.length > 0) {
var ul = angular.element('<ul>');
var children = parNode.children();
var lastChild = angular.element(children[children.length - 1]);
lastChild.find('recur').replaceWith(ul);
buildTree(ul, level + 1, node.children, nodeScope, ident, transclude);
}
}
}
return {
restrict: 'A',
transclude: true,
terminal: true,
priority: 2000,
compile: function(elem, attr, transclude) {
return function(scope, elem, attr) {
var nodes = scope.$eval(attr.roots);
scope.$watch(attr.roots, function(o,n) {
elem.children().remove();
buildTree(elem, 0, nodes, scope, attr.item, transclude);
elem.find('recur').remove();
}, true);
};
}
};
});
/* CSS goes here */
ul { list-style:none; margin:0; padding:0; }
.node:hover { background-color:#f0f0f0; }