Skip to content

Instantly share code, notes, and snippets.

@matthewbednarski
Created March 10, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewbednarski/780f63bd98dba03c9574 to your computer and use it in GitHub Desktop.
Save matthewbednarski/780f63bd98dba03c9574 to your computer and use it in GitHub Desktop.
An AngularJS tree directive example An AngularJS tree directive example // source http://jsbin.com/batilixaqa
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="An AngularJS tree directive example">
<meta name="link-inspiration" content="http://stackoverflow.com/questions/14430655/recursion-in-angular-directives">
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<script src="https://rawgit.com/lodash/lodash/3.0.1/lodash.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<meta charset="utf-8">
<title>An AngularJS tree directive example</title>
</head>
<body ng-view>
<div ng-controller='treeItems'>
<tree family="family" />
</div>
<script id="jsbin-javascript">
var module = angular.module('app', []);
module
.controller('treeItems', ['$scope',
function($scope) {
$scope.family = {
name: 'test',
parent: undefined,
children: []
};
}
])
.factory('RecursionHelper', ['$compile',
// taken from http://stackoverflow.com/questions/14430655/recursion-in-angular-directives
function($compile) {
return {
/**
* Manually compiles the element, fixing the recursion loop.
* @param element
* @param [link] A post-link function, or an object with function(s) registered via pre and post properties.
* @returns An object containing the linking functions.
*/
compile: function(element, link) {
// Normalize the link parameter
if (angular.isFunction(link)) {
link = {
post: link
};
}
// Break the recursion loop by removing the contents
var contents = element.contents().remove();
var compiledContents;
return {
pre: (link && link.pre) ? link.pre : null,
/**
* Compiles and re-adds the contents
*/
post: function(scope, element) {
// Compile the contents
if (!compiledContents) {
compiledContents = $compile(contents);
}
// Re-add the compiled contents to the element
compiledContents(scope, function(clone) {
element.append(clone);
});
// Call the post-linking function, if any
if (link && link.post) {
link.post.apply(null, arguments);
}
}
};
}
};
}
])
.directive("tree", function(RecursionHelper) {
return {
restrict: "E",
scope: {
family: '='
},
template: '<p>{{ family.name }}</p>' +
'<button ng-click="addChild( family );"><i class="fa fa-arrow-right"></i></button>' +
'<div ng-if="family.parent" >' +
'<button ng-click="addChild( family.parent );"><i class="fa fa-arrow-down"></i></button>' +
'<button ng-click="remove( family );"><i class="fa fa-trash-o"></i></button>' +
'</div>' +
'<ul>' +
'<li ng-repeat="child in family.children">' +
'<tree family="child"></tree>' +
'</li>' +
'</ul>',
compile: function(element) {
var link = function($scope, ele, attr) {
$scope.remove = function(fam) {
var idx = fam.parent.children.indexOf(fam);
fam.parent.children.splice(idx, 1);
};
$scope.addChild = function(fam) {
var newName = _.uniqueId(fam.name);
var newFam = {
name: newName,
parent: $scope.family,
children: []
};
$scope.family.children.push(newFam);
};
};
// Use the compile function from the RecursionHelper,
// And return the linking function(s) which it returns
return RecursionHelper.compile(element, link);
}
};
});
angular.bootstrap(document, ['app']);
</script>
<script id="jsbin-source-html" type="text/html"><!DOCTYPE html>
<html>
<head>
<meta name="description" content="An AngularJS tree directive example">
<meta name="link-inspiration" content="http://stackoverflow.com/questions/14430655/recursion-in-angular-directives">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<script src="https://rawgit.com/lodash/lodash/3.0.1/lodash.min.js"><\/script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"><\/script>
<meta charset="utf-8">
<title>An AngularJS tree directive example</title>
</head>
<body ng-view>
<div ng-controller='treeItems'>
<tree family="family" />
</div>
</body>
</html></script>
<script id="jsbin-source-javascript" type="text/javascript">var module = angular.module('app', []);
module
.controller('treeItems', ['$scope',
function($scope) {
$scope.family = {
name: 'test',
parent: undefined,
children: []
};
}
])
.factory('RecursionHelper', ['$compile',
// taken from http://stackoverflow.com/questions/14430655/recursion-in-angular-directives
function($compile) {
return {
/**
* Manually compiles the element, fixing the recursion loop.
* @param element
* @param [link] A post-link function, or an object with function(s) registered via pre and post properties.
* @returns An object containing the linking functions.
*/
compile: function(element, link) {
// Normalize the link parameter
if (angular.isFunction(link)) {
link = {
post: link
};
}
// Break the recursion loop by removing the contents
var contents = element.contents().remove();
var compiledContents;
return {
pre: (link && link.pre) ? link.pre : null,
/**
* Compiles and re-adds the contents
*/
post: function(scope, element) {
// Compile the contents
if (!compiledContents) {
compiledContents = $compile(contents);
}
// Re-add the compiled contents to the element
compiledContents(scope, function(clone) {
element.append(clone);
});
// Call the post-linking function, if any
if (link && link.post) {
link.post.apply(null, arguments);
}
}
};
}
};
}
])
.directive("tree", function(RecursionHelper) {
return {
restrict: "E",
scope: {
family: '='
},
template: '<p>{{ family.name }}</p>' +
'<button ng-click="addChild( family );"><i class="fa fa-arrow-right"></i></button>' +
'<div ng-if="family.parent" >' +
'<button ng-click="addChild( family.parent );"><i class="fa fa-arrow-down"></i></button>' +
'<button ng-click="remove( family );"><i class="fa fa-trash-o"></i></button>' +
'</div>' +
'<ul>' +
'<li ng-repeat="child in family.children">' +
'<tree family="child"></tree>' +
'</li>' +
'</ul>',
compile: function(element) {
var link = function($scope, ele, attr) {
$scope.remove = function(fam) {
var idx = fam.parent.children.indexOf(fam);
fam.parent.children.splice(idx, 1);
};
$scope.addChild = function(fam) {
var newName = _.uniqueId(fam.name);
var newFam = {
name: newName,
parent: $scope.family,
children: []
};
$scope.family.children.push(newFam);
};
};
// Use the compile function from the RecursionHelper,
// And return the linking function(s) which it returns
return RecursionHelper.compile(element, link);
}
};
});
angular.bootstrap(document, ['app']);</script></body>
</html>
var module = angular.module('app', []);
module
.controller('treeItems', ['$scope',
function($scope) {
$scope.family = {
name: 'test',
parent: undefined,
children: []
};
}
])
.factory('RecursionHelper', ['$compile',
// taken from http://stackoverflow.com/questions/14430655/recursion-in-angular-directives
function($compile) {
return {
/**
* Manually compiles the element, fixing the recursion loop.
* @param element
* @param [link] A post-link function, or an object with function(s) registered via pre and post properties.
* @returns An object containing the linking functions.
*/
compile: function(element, link) {
// Normalize the link parameter
if (angular.isFunction(link)) {
link = {
post: link
};
}
// Break the recursion loop by removing the contents
var contents = element.contents().remove();
var compiledContents;
return {
pre: (link && link.pre) ? link.pre : null,
/**
* Compiles and re-adds the contents
*/
post: function(scope, element) {
// Compile the contents
if (!compiledContents) {
compiledContents = $compile(contents);
}
// Re-add the compiled contents to the element
compiledContents(scope, function(clone) {
element.append(clone);
});
// Call the post-linking function, if any
if (link && link.post) {
link.post.apply(null, arguments);
}
}
};
}
};
}
])
.directive("tree", function(RecursionHelper) {
return {
restrict: "E",
scope: {
family: '='
},
template: '<p>{{ family.name }}</p>' +
'<button ng-click="addChild( family );"><i class="fa fa-arrow-right"></i></button>' +
'<div ng-if="family.parent" >' +
'<button ng-click="addChild( family.parent );"><i class="fa fa-arrow-down"></i></button>' +
'<button ng-click="remove( family );"><i class="fa fa-trash-o"></i></button>' +
'</div>' +
'<ul>' +
'<li ng-repeat="child in family.children">' +
'<tree family="child"></tree>' +
'</li>' +
'</ul>',
compile: function(element) {
var link = function($scope, ele, attr) {
$scope.remove = function(fam) {
var idx = fam.parent.children.indexOf(fam);
fam.parent.children.splice(idx, 1);
};
$scope.addChild = function(fam) {
var newName = _.uniqueId(fam.name);
var newFam = {
name: newName,
parent: $scope.family,
children: []
};
$scope.family.children.push(newFam);
};
};
// Use the compile function from the RecursionHelper,
// And return the linking function(s) which it returns
return RecursionHelper.compile(element, link);
}
};
});
angular.bootstrap(document, ['app']);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment