10

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

这是我的代码:

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");
        }
    };
});

树视图模板:

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

树视图项目模板:

<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>

在 treeview 指令$scope.items中为开发而硬编码 - 最终我希望这将来自从服务器中提取数据的控制器/服务。然而,它代表了我正在寻找的那种基本结构。

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

没有嵌套 ul 的 JSFiddle - 工作:

http://jsfiddle.net/BdmV3/

带有嵌套 ul 的 JSFiddle - 不起作用(并且可能会挂起您的浏览器!):

http://jsfiddle.net/SKPpv/

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

4

1 回答 1

15

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

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

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/

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

于 2013-08-11T20:59:52.380 回答