简体   繁体   English

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

[英]Looping through deep objects in ng-repeat

I'm in angular and i have a object like this. 我有角度,我有一个像这样的对象。

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

I wan't to loop through all of these so i have something like this. 我不想遍历所有这些,所以我有这样的东西。

• Something •某事

• Hello World • 你好,世界

• Hello Overflow •Hello溢出

• John Doe •John Doe

• Amazing Title •惊人的标题

• Google it • 谷歌一下

• I'm a child •我还是个孩子

• Another •另一个

• He's my brother •他是我的兄弟

• She's my mother •她是我的母亲

• You never know if I'm going to have children •你永远不知道我是否会生孩子

The problem is I wouldn't know how deep this object will go or what's in it. 问题是我不知道这个物体的深度或者它的含义。 so I wouldn't be able to do it manually. 所以我无法手动完成。 I have done a basic loop with ng-repeat in the fiddle provided at the bottom, but i can't figure out how I can automatically loop through these and create nested <ul> 's and <li> 's. 我在底部提供的小提琴中用ng-repeat做了一个基本循环,但我无法弄清楚如何自动循环这些并创建嵌套的<ul><li>

What would be the best way to accomplish this? 实现这一目标的最佳方法是什么?

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

You don't need to make a custom directive, what you want is to use an inline template that calls it's self. 您不需要创建自定义指令,您想要的是使用内联模板来调用它自己。

I forked your fiddle. 我分叉你的小提琴。

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

basically it looks like this: 基本上它看起来像这样:

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

I should note that you are not actually overwriting x , since angular creates a new scope for each repeated item. 我应该注意到你实际上并没有覆盖x ,因为angular会为每个重复的项目创建一个新的范围。

Here you go: 干得好:

html HTML

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

JavaScript 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);
            }
        }
    };
}]);

I forked your fiddle: 我分叉你的小提琴:

http://jsfiddle.net/c4Kp8/ http://jsfiddle.net/c4Kp8/

Actually I must confess that I like Master Morality's approach but you can also go with a custom directive. 实际上我必须承认我喜欢Master Morality的方法,但你也可以选择自定义指令。 The key thing to know if you go that route is that you need to intercept on the item level to manually check if the current item has children, and if so, $compile the directive for the node yourself. 要知道你是否走这条路线的关键是你需要在项目级别上拦截以手动检查当前项目是否有子项,如果是,则自行编译该节点的指令。

UPDATE UPDATE

However, there is one thing that should bother us in the above code. 但是,在上面的代码中有一件事应该让我们烦恼。 The duplication of html code (inlined in the directive) is a code smell. 复制html代码(在指令中内联)是代码气味。 If you like, you can get really funky and fix this by introducing a generic template-code directive which doesn't do anything else but providing the code of the node where it is applied on as a template for other directives. 如果你愿意,你可以通过引入一个通用的template-code指令来解决这个问题,除了提供应用它的节点的代码作为其他指令的模板之外,它还可以解决这个问题。

So then our solution would look like this: 那么我们的解决方案将如下所示:

html 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 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/ Plunker: http//jsfiddle.net/2rQWf/

You're probably going to need to create your own directive passing in the object to iterate over. 您可能需要创建自己的指令传入对象以进行迭代。 Put a watch on the object passed in and when that fires run some recursive function that appends elements to the element that the directive is on. 监视传入的对象以及何时触发运行一些递归函数,该函数将元素追加到指令所在的元素。

You can get at the DOM element from the element parameter on the directive link function. 您可以从指令链接函数的element参数获取DOM元素。 You can obviously append DOM elements using that same element parameter. 显然,您可以使用相同的元素参数附加DOM元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM