3

我有棱角,我有一个像这样的物体。

var items = [{
    title: 'Something',
    children: [
        { title: 'Hello World' },
        { title: 'Hello Overflow' },
        { title: 'John Doe', children: [
            { title: 'Amazing title' },
            { title: 'Google it' },
            { title: 'I'm a child', children: [
                { title: 'Another ' },
                { title: 'He\'s my brother' },
                { title: 'She\'s my mother.', children: [
                    {title: 'You never know if I'm going to have children'}
                ]}
            ]}
        ]}
    ]
}];

我不想遍历所有这些,所以我有这样的东西。

    • 某物

       • 你好世界

       • 你好溢出

       • 约翰·多伊

          • 惊人的标题

          • 去谷歌上查询

          • 我是个孩子

              • 其他

              • 他是我的兄弟

              • 她是我妈妈

                  • 你永远不知道我是否要生孩子

问题是我不知道这个物体会走多深或里面有什么。所以我无法手动完成。我ng-repeat在底部提供的小提琴中完成了一个基本循环,但我不知道如何自动循环这些并创建嵌套<ul>的 's 和<li>'s。

实现这一目标的最佳方法是什么?

演示:http: //jsfiddle.net/XtgLM/

4

3 回答 3

9

您不需要制作自定义指令,您想要的是使用一个调用它的内联模板。

我叉了你的小提琴。

http://jsfiddle.net/MasterMorality/E99Gh/2/

基本上它看起来像这样:

<script type='text/ng-template' id="item.html">
    ...
    <div ng-repeat="x in x.childrens" ng-include="'item.html'"></div>
</script>
...
<div ng-repeat="x in things" ng-include="'item.html'"></div>

我应该注意,您实际上并没有覆盖x,因为 angular 为每个重复的项目创建了一个新范围。

于 2013-08-23T17:59:11.587 回答
8

干得好:

html

<div ng-app="app" ng-controller="test">
   <ul>
       <li nested-item ng-repeat="item in items">{{item.title}}</li>
   </ul>         
</div>

JavaScript

var items = [{
    title: 'Something',
    children: [
        { title: 'Hello World' },
        { title: 'Hello Overflow' },
        { title: 'John Doe', children: [
            { title: 'Amazing title' },
            { title: 'Google it' },
            { title: 'Im a child', children: [
                { title: 'Another ' },
                { title: 'He\'s my brother' },
                { title: 'She\'s my mother.', children: [
                    {title: 'You never know if im going to have children'}
                ]}
            ]}
        ]}
    ]
}];

var app = angular.module('app', []);

app.controller('test', function( $scope ) {
    $scope.items = items;
});


app.directive('nestedItem', ['$compile', function($compile){
    return {
        restrict: 'A',
        link: function(scope, element){
        console.log(element);
            if (scope.item.children){
                var html = $compile('<ul><li nested-item ng-repeat="item in item.children">{{item.title}}</li></ul>')(scope);
                element.append(html);
            }
        }
    };
}]);

我叉了你的小提琴:

http://jsfiddle.net/c4Kp8/

实际上,我必须承认我喜欢 Master Morality 的方法,但您也可以使用自定义指令。要知道你是否走这条路的关键是你需要在项目级别拦截以手动检查当前项目是否有子项,如果有,则 $compile 自己的节点指令。

更新

然而,在上面的代码中有一件事情应该困扰我们。html 代码的重复(在指令中内联)是代码异味。如果您愿意,您可以通过引入一个通用template-code指令来解决这个问题,该指令不做任何其他事情,但提供应用它的节点的代码作为其他指令的模板。

那么我们的解决方案将如下所示:

html

<div ng-app="app" ng-controller="test">
   <ul template-code>
       <li nested-item ng-repeat="item in items">{{item.title}}</li>
   </ul>         
</div>

JavaScript

var items = [{
    title: 'Something',
    children: [
        { title: 'Hello World' },
        { title: 'Hello Overflow' },
        { title: 'John Doe', children: [
            { title: 'Amazing title' },
            { title: 'Google it' },
            { title: 'Im a child', children: [
                { title: 'Another ' },
                { title: 'He\'s my brother' },
                { title: 'She\'s my mother.', children: [
                    {title: 'You never know if im going to have children'}
                ]}
            ]}
        ]}
    ]
}];

var app = angular.module('app', []);

app.controller('test', function( $scope ) {
    $scope.items = items;
});

app.directive('templateCode', function(){
    return {
        restrict: 'A',
        controller: function(){},
        compile: function(element){
            element.removeAttr('template-code');
            //ATTENTION: We need to trim() here. Otherwise AngularJS raises an exception
            //later when we want to use the templateCode in a $compile function. 
            //Be aware that we assume a modern browser 
            //that already ships with a trim function.
            //It's easy to secure that with a polyfill.
            var templateCode = element.parent().html().trim();
            return function(scope, iElement, iAttrs, controller){
                controller.templateCode = templateCode;
            }
        }
    }
});

app.directive('nestedItem', ['$compile', function($compile){
    return {
        restrict: 'A',
        require: '^templateCode',
        link: function(scope, element, iAttr, controller){ 
            if (scope.item.children){
                scope.items = scope.item.children;         
                var html = $compile(controller.templateCode)(scope);
                element.append(html);
            }
        }
    };
}]);

Plunker:http: //jsfiddle.net/2rQWf/

于 2013-08-23T18:08:51.207 回答
0

您可能需要创建自己的指令来传递对象以进行迭代。监视传入的对象,并在触发时运行一些递归函数,将元素附加到指令所在的元素上。

您可以从指令链接函数的元素参数中获取 DOM 元素。您显然可以使用相同的元素参数附加 DOM 元素。

于 2013-08-23T17:39:50.603 回答