我有一个树形结构,需要为三个树中的每个级别设置不同的样式。因此我需要一些方法来跟踪项目所在的级别,所以我认为如果有某种方法可以动态地为ng-repeat
(不是内部项目)设置唯一ID,我可以轻松地执行一些数学给出正确的内联样式。
现在我有一个使用三个文件的递归树结构;包装器,新级别和分支(与新级别相同)。 treeWrapper
和treeLevel
是使用这些模板的指令。
我在ng-include
文件中执行了tree-branch.html
以使其递归。 ng-include
内的第一个tree-level.html
仅适用于" kickstart"递归。
所以我的问题是如何为树中的每个ng-repeat
设置一个id?这甚至可能吗?
tree-wrapper.html
:
<div class="tree-wrapper">
<tree-level ctrl="ctrl" tree="tree"></tree-level>
</div>
tree-level.html
:
<ul class="tree-list">
<li class="tree-item" ng-repeat="branch in tree track by $index"
ng-include="'/app/views/components/tree/tree-branch.html'"></li>
</ul>
tree-branch.html
:
<div ng-click="ctrl.toggleBranch(branch)" ng-bind="branch.name"></div>
<ul class="tree-list" ng-if="branch.branches">
<li class="tree-item" style="padding-left: {{$index * 5}}" ng-repeat="branch in branch.branches"
ng-include="'/app/views/components/tree/tree-branch.html'"></li>
</ul>
答案 0 :(得分:2)
这可以通过使用指令而不是包含来轻松完成。
树枝模板如下所示:
<ul class="branch-level-{{vm.level}}">
<li ng-repeat="branch in vm.branch.branches">
<tree-branch level="vm.level + 1" branch="branch"></tree-branch>
</li>
</ul>
指令定义类似于
{
scope : {
level : '=',
branch : '='
}
}
tree-level.html
中的kickstart可以简化:
<tree-branch level="0" branch="tree"></tree-branch>
请注意,使用指令的递归会炸毁编译器,您必须自己处理它。请参阅此帖子以了解如何操作:Recursion in Angular directives
/*
* An Angular service which helps with creating recursive directives.
* @author Mark Lagendijk
* @license MIT
*/
angular.module('RecursionHelper', []).factory('RecursionHelper', ['$compile',
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);
}
}
};
}
};
}
]);
angular.module('recursionDemo', ['RecursionHelper'])
.controller("TreeController", function($scope) {
$scope.treeFamily = {
name: "Parent",
children: [{
name: "Child1",
children: [{
name: "Grandchild1",
children: []
}, {
name: "Grandchild2",
children: [{
name: "GrandGrandchild1",
children: []
}]
}, {
name: "Grandchild3",
children: []
}]
}, {
name: "Child2",
children: []
}]
};
})
.directive("tree", function(RecursionHelper) {
return {
restrict: "E",
scope: {},
bindToController: {
family: '=',
level: '='
},
controller: function() {},
controllerAs: 'vm',
template: '{{vm.family.name}} Level = {{vm.level}} ' +
'<ul>' +
' <li ng-repeat="child in vm.family.children">' +
' <tree family="child" level="vm.level+1"></tree>' +
' </li>' +
'</ul>',
compile: function(element) {
return RecursionHelper.compile(element, function(scope, iElement, iAttrs, controller, transcludeFn) {
// Define your normal link function here.
// Alternative: instead of passing a function,
// you can also pass an object with
// a 'pre'- and 'post'-link function.
});
}
};
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="recursionDemo" ng-controller="TreeController">
<tree family="treeFamily" level="0"></tree>
</div>
&#13;