循环遍历ng-repeat中的深层对象

时间:2013-08-23 17:25:37

标签: javascript angularjs

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

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'}
                ]}
            ]}
        ]}
    ]
}];

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

  

•某事

     

•Hello World

     

•Hello Overflow

     

•John Doe

     

•惊人的标题

     

•谷歌

     

•我还是个孩子

     

•另一个

     

•他是我的兄弟

     

•她是我的母亲

     

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

问题是我不知道这个物体的深度或者物体的含义。所以我无法手动完成。我在底部提供的小提琴中使用ng-repeat做了一个基本循环,但我无法弄清楚如何自动循环这些并创建嵌套的<ul><li>的。

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

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

3 个答案:

答案 0 :(得分:8)

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

我把你的小提琴分开了。

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会为每个重复的项目创建一个新的范围。

答案 1 :(得分: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的方法,但你也可以使用自定义指令。要知道你是否走这条路线的关键是你需要在项目级别上拦截以手动检查当前项目是否有子项,如果是,则自行编译该节点的指令。

<强>更新

但是,在上面的代码中有一件事应该让我们烦恼。复制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/

答案 2 :(得分:0)

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

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