有几个流行的递归角度指令Q& A在那里,所有归结为以下解决方案之一:
>基于运行时作用域状态手动递增“编译”HTML
> example 1 [stackoverflow]
> example 2 [angular jsfiddles page]
> do not use a directive at all,but a< script>模板本身
第一个有一个问题,你不能删除以前编译的代码,除非你可以理解地管理手动编译过程。第二种方法的问题是…不是一个指令,错过了它的强大功能,但更迫切的是,它不能参数化方式与指令是一样的;它只是绑定到一个新的控制器实例。
我一直玩在手工做一个angular.bootstrap或@compile()在链接功能,但这让我有手动跟踪元素删除和添加的问题。
有没有好的方法有一个参数化的递归模式管理添加/删除元素来反映运行时状态?也就是说,一个树具有添加/删除节点按钮和一些输入字段,其值沿着节点的子节点传递。也许第二种方法与链接范围的组合(但我不知道如何做到这一点)?
在通过@ dnc253提到的thread中的描述的解决方案的启发,我抽象的递归功能
into a service。
module.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); } } }; } }; }]);
其用法如下:
module.directive("tree",["RecursionHelper",function(RecursionHelper) { return { restrict: "E",scope: {family: '='},template: '<p>{{ family.name }}</p>'+ '<ul>' + '<li ng-repeat="child in family.children">' + '<tree family="child"></tree>' + '</li>' + '</ul>',compile: function(element) { // Use the compile function from the RecursionHelper,// And return the linking function(s) which it returns return RecursionHelper.compile(element); } }; }]);
>你不需要一个特殊的指令,使你的HTML不那么干净。>递归的逻辑抽象消失在RecursionHelper服务,让你保持你的指令干净。