I'm trying to create a treeview using AngularJS.
Here's my code:
module.directive('treeview', function () {
return {
restrict: 'E',
templateUrl: "/templates/ui/controls/treeview.htm",
replace: true,
transclude: true,
scope: {},
link: function (scope, element, attrs) {
console.log("treeview directive loaded");
},
controller: function ($scope, $rootScope) {
$rootScope.depth = 0;
$scope.items = [
{ text: "face" },
{ text: "palm" },
{
text: "cake",
childitems: [
{ text: "1 face" },
{ text: "1 palm" },
{ text: "1 cake" }
]
}
];
}
};
});
module.directive('treeviewItem', function () {
return {
restrict: 'E',
templateUrl: "/templates/ui/controls/treeview-item.htm",
replace: true,
scope: {
item: "="
},
link: function (scope, element, attrs) {
console.log("treeview item directive loaded");
}
};
});
Treeview template:
<div class="sl-treeview">
<ul class="clear" ng-transclude>
<treeview-item ng-repeat="item in items" item="item"></treeview-item>
</ul>
</div>
Treeview Item template:
<li>
<i class="icon-plus-sign"></i>
<a href="/">
<i class="icon-folder-close"></i>
{{item.text}}
</a>
<!-- This ul is the issue - it crashes the page -->
<ul>
<treeview-item ng-repeat="childitem in item.childitems" item="childitem"></treeview-item>
</ul>
</li>
In the treeview directive $scope.items
is hardcoded for development - eventually I hope this will come from a controller/service pulling data from the server. However it represents the sort of basic structure I'm looking for.
When I run this without the nested ul in treeviewItem it gives me the first three items just fine. When i add the ul in to try and get the controls to bind with child items it hands the page and stops working.
JSFiddle without nested ul - working:
http://jsfiddle.net/BdmV3/
JSFiddle with nested ul - not working (and may hang your browser!):
http://jsfiddle.net/SKPpv/
How should I go about making a control that uses a custom directive and ngRepeat to create potentially infinite levels of recursion? Why isn't my approach working?
The problem is that you're trying to define your directive recursively, when angular was trying to compile the template, it saw treeview
directive, it called treeview
's compile function, then it saw treeviewItem
directive, it called treeviewItem
's compile function, then it saw treeviewItem
directive, it called treeviewItem
's compile function,then it saw treeviewItem
directive, it called treeviewItem
's compile function...
See the problem? The calls to compile functions couldn't stop. So, you need to pull the recursive definition out of your template, but use $compile
to build DOM manually:
module.directive('treeviewItem', function ($compile) {
return {
restrict: 'E',
template: '<li><i class="icon-plus-sign"></i><a href="/"><i class="icon-folder-close"></i>{{item.text}}</a></li>',
replace: true,
scope: {
item: "="
},
link: function (scope, element, attrs) {
element.append($compile('<ul><treeview-item ng-repeat="childitem in item.childitems" item="childitem"></treeview-item></ul>')(scope));
console.log("treeview item directive loaded");
}
};
});
http://jsfiddle.net/SKPpv/3/
Alternatively, I found a solution to display tree-like data on SO https://stackoverflow.com/a/11861030/69172. The solution however uses ngInclude
instead of directives.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With