一尘不染

遍历ng-repeat中的深层对象

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

我不会遍历所有这些,所以我有这样的事情。

•东西

• 你好,世界

•您好溢出

•约翰·杜

•惊人的标题

• 谷歌一下

•我还是个孩子

•另一个

•他是我的兄弟

•她是我妈妈

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

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

做到这一点的最佳方法是什么?

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


阅读 227

收藏
2020-07-04

共1个答案

一尘不染

干得好:

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/

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

更新

但是,上面的代码中有一件事应该困扰我们。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);
            }
        }
    };
}]);

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

2020-07-04