使用 ngRepeat 递归自定义指令 [英] Recursive custom directives using ngRepeat

查看:33
本文介绍了使用 ngRepeat 递归自定义指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 AngularJS 创建树视图.

这是我的代码:

module.directive('treeview', function () {返回 {限制:'E',templateUrl: "/templates/ui/controls/treeview.htm",替换:真的,转置:真实,范围: {},链接:函数(范围、元素、属性){console.log("treeview 指令加载");},控制器:函数($scope,$rootScope){$rootScope.depth = 0;$scope.items = [{文字:脸"},{文字:手掌"},{文字:蛋糕",子项:[{文字:1张脸"},{文字:1手掌"},{ 文字:1 个蛋糕"}]}];}};});module.directive('treeviewItem', function () {返回 {限制:'E',templateUrl: "/templates/ui/controls/treeview-item.htm",替换:真的,范围: {项目:="},链接:函数(范围、元素、属性){console.log("treeview item 指令加载");}};});

树视图模板:

<ul class="clear" ng-transclude><treeview-item ng-repeat="item in items" item="item"></treeview-item>

Treeview 项目模板:

  • <i class="icon-plus-sign"></i><i class="icon-folder-close"></i>{{item.text}}</a><!-- 这个 ul 是问题所在-它使页面崩溃--><ul><treeview-item ng-repeat="item.childitems 中的childitem" item="childitem"></treeview-item>
  • 在 treeview 指令中 $scope.items 被硬编码用于开发 - 最终我希望这将来自控制器/服务从服务器拉取数据.然而,它代表了我正在寻找的那种基本结构.

    当我在 treeviewItem 中没有嵌套 ul 的情况下运行它时,它给了我前三个项目就好了.当我添加 ul 以尝试让控件与子项绑定时,它会传递页面并停止工作.

    没有嵌套 ul 的 JSFiddle - 工作:

    http://jsfiddle.net/BdmV3/

    带有嵌套 ul 的 JSFiddle - 不工作(可能会挂掉您的浏览器!):

    http://jsfiddle.net/SKPpv/

    我应该如何制作使用自定义指令和 ngRepeat 的控件来创建潜在的无限递归级别?为什么我的方法不起作用?

    解决方案

    问题是你试图递归地定义你的指令,当 angular 试图编译模板时,它看到了 treeview指令,它调用treeview的编译函数,然后它看到treeviewItem指令,它调用treeviewItem的编译函数,然后它看到treeviewItem 指令,它调用了treeviewItem 的编译函数,然后它看到了treeviewItem 指令,它调用了treeviewItem 的编译函数...

    看到问题了吗?对编译函数的调用无法停止.因此,您需要从模板中提取递归定义,但使用 $compile 手动构建 DOM:

    module.directive('treeviewItem', function ($compile) {返回 {限制:'E',模板:'<li><i class="icon-plus-sign"></i><a href="/"><i class="icon-folder-close"></i>{{item.text}}</a></li>',替换:真的,范围: {项目:="},链接:函数(范围、元素、属性){element.append($compile('<ul><treeview-item ng-repeat="childitem in item.childitems" item="childitem"></treeview-item></ul>')(范围));console.log("treeview item 指令加载");}};});

    http://jsfiddle.net/SKPpv/3/

    或者,我找到了一种在 SO https://stackoverflow.com/a/11861030/69172 上显示树状数据的解决方案.然而,该解决方案使用 ngInclude 而不是指令.

    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.

    这篇关于使用 ngRepeat 递归自定义指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆