2016-03-29 21 views
0

对于像我这样的AngularJS新手来说,这是一项具有挑战性的任务,所以我想问一些帮助或帮助。所以我想实现的是通过树级别和树ID对数据进行分组。Angular JS根据级别渲染树型数据树

我对HTML当前代码:

<!DOCTYPE html> 
<html> 
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> 

<body> 

    <div ng-app="myApp" ng-controller="myCtrl"> 
     <ul> 
      <li ng-repeat="item in list"> 
       [[ item.code ]] 

      </li> 
     </ul> 
    </div> 

</body> 

</html> 

我对JS当前代码:

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

app.controller('myCtrl', function($scope) { 

    $scope.list = [ 
     { 
      "id": 1, 
      "code": "TANK", 
      "tree_id": 1, 
      "level": 0, 
      "parent": null 
     }, 
     { 
      "id": 2, 
      "code": "OIL", 
      "tree_id": 1, 
      "level": 1, 
      "parent": 1 
     }, 
     { 
      "id": 3, 
      "code": "CHEM", 
      "tree_id": 1, 
      "level": 1, 
      "parent": 1 
     }, 
     { 
      "id": 6, 
      "code": "PROD", 
      "tree_id": 1, 
      "level": 2, 
      "parent": 3 
     }, 
     { 
      "id": 4, 
      "code": "BULK", 
      "tree_id": 2, 
      "level": 0, 
      "parent": null 
     }, 
     { 
      "id": 5, 
      "code": "LOG", 
      "tree_id": 2, 
      "level": 1, 
      "parent": 4 
     } 
    ], 
}); 

如果您检查$ scope.list,你可以找到tree_id,水平和父。所以我真正想要实现的是通过树ID对对象进行分组,然后级别0或顶级将成为一级,而级别1和级别将只是可折叠内容。请认为tree_id作为对象之间的分组,可以将级别视为其层次结构顺序,而继承层次结构根将取决于父树的整数值,这是树ID。另外请注意,这并不局限于一个分支,但多,灵活的和无限的分支

渲染应该是这个样子:

  • TANK
    • CHEM
      • PROD
  • BULK
    • LOG
+0

你可以改变'$ scope.list'的结构吗?或者你必须使用现有的结构吗? – S4beR

+0

现有的结构是一样的,实际上它来自于API响应 –

回答

1

它在StackOverflow上本已讨论。您可以使用以下链接。

How can I group data with an Angular filter?

使用GROUPBY过滤器可以实现树状结构。

+0

嗨!我很欣赏答案,但我有点改变了一个更有趣和具有挑战性的问题。您链接中的答案仅限于一个级别 –

0

in angular groupBy work's for object not for array。所以你可以根据需要在你的控制器中生成这个。

我可以告诉你一个生成过程,只要你想。如果想要的话可​​以试试。

在你的控制器调用一个函数后得到你list从api。

$scope.newList = {parents:[],childs:[]}; 


    var generateNav = function(parent) { 
     $scope.newList.parents.push(parent); 
     angular.forEach($scope.list, function(item) { 
     if(item.tree_id === parent.tree_id) { 
      $scope.newList.childs.push(item); 
     } 
     }) 
    }; 

    var generateNewList = function(list) { 
     angular.forEach(list, function(item) { 
     if(item.level === 0) { 
     generateNav(item); 
     } 
     }); 
    }; 

    // after api cal and get data call this function with your `list` 
    generateNewList($scope.list); 

,并在HTML中:使用newList

<ul> 
      <li ng-repeat="item in newList.parents"> 
       {{ item.code }} 
       <ul> 
       <li ng-repeat="child in newList.childs" ng-if="child.tree_id === item.tree_id && item.id!==child.id">{{child.code}}</li> 
       </ul> 
      </li> 
     </ul> 

,您可以访问PLUNKER DEMO LINK

+0

嗨!我很欣赏答案,但我有点改变了一个更有趣和具有挑战性的问题 –

1

您可以和使用自定义指令来处理递归层次:

编辑添加的属性REF in directives and your new array structure

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

 
app.directive('collection', function() { 
 
\t return { 
 
\t \t restrict : "E", 
 
\t \t replace : true, 
 
     transclude: true, 
 
\t \t scope : { 
 
\t \t \t collection : '=', 
 
\t \t \t list : '=', 
 
\t \t \t coldisplay : '=', 
 
\t \t \t colfrom : '=', 
 
\t \t \t colto : '=' 
 
\t \t }, 
 
\t \t template : "<ul><member ng-repeat='member in collection track by $index' member='member' list='list' coldisplay='coldisplay' colfrom='colfrom' colto='colto'></member></ul>" 
 
\t }; 
 
}); 
 

 
app.directive('member', function ($compile) { 
 
\t return { 
 
\t \t restrict : "E", 
 
\t \t replace : true, 
 
     transclude: true, 
 
\t \t scope : { 
 
\t \t \t member : '=', 
 
\t \t \t list : '=', 
 
\t \t \t coldisplay : '=', 
 
\t \t \t colfrom : '=', 
 
\t \t \t colto : '=' 
 
\t \t }, 
 
\t \t template : "<li>{{member[coldisplay]}}</li>", 
 
\t \t link : function (scope, element, attrs) { 
 
\t \t \t scope.children = []; 
 
\t \t \t angular.forEach(scope.list, function (value, key) { 
 
\t \t \t \t if (value[scope.colfrom] === scope.member[scope.colto]) { 
 
\t \t \t \t \t this.push(value); 
 
\t \t \t \t } 
 
\t \t \t }, scope.children); 
 

 
\t \t \t if (scope.children.length > 0) { 
 
\t \t \t \t element.append("<collection collection='children' list='list' coldisplay='coldisplay' colfrom='colfrom' colto='colto'></collection>"); 
 
\t \t \t \t $compile(element.contents())(scope); 
 
\t \t \t } 
 
\t \t } 
 
\t } 
 
}); 
 

 
app.controller('myCtrl', function ($scope) { 
 

 
\t $scope.list = [{ 
 
\t \t \t "id" : 1, 
 
\t \t \t "code" : "TANK", 
 
\t \t \t "tree_id" : 1, 
 
\t \t \t "level" : 0, 
 
\t \t \t "parent" : null 
 
\t \t }, { 
 
\t \t \t "id" : 2, 
 
\t \t \t "code" : "OIL", 
 
\t \t \t "tree_id" : 1, 
 
\t \t \t "level" : 1, 
 
\t \t \t "parent" : 1 
 
\t \t }, { 
 
\t \t \t "id" : 3, 
 
\t \t \t "code" : "CHEM", 
 
\t \t \t "tree_id" : 1, 
 
\t \t \t "level" : 1, 
 
\t \t \t "parent" : 1 
 
\t \t }, { 
 
\t \t \t "id" : 6, 
 
\t \t \t "code" : "PROD", 
 
\t \t \t "tree_id" : 1, 
 
\t \t \t "level" : 2, 
 
\t \t \t "parent" : 3 
 
\t \t }, { 
 
\t \t \t "id" : 4, 
 
\t \t \t "code" : "BULK", 
 
\t \t \t "tree_id" : 2, 
 
\t \t \t "level" : 0, 
 
\t \t \t "parent" : null 
 
\t \t } 
 
\t ]; 
 

 
\t $scope.rootList = []; 
 

 
\t angular.forEach($scope.list, function (value, key) { 
 
\t \t if (value.parent == null) { 
 
\t \t \t this.push(value); 
 
\t \t } 
 
\t }, $scope.rootList); 
 

 
})
<html> 
 
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> 
 

 
<body> 
 
    <div ng-app="myApp" ng-controller="myCtrl"> 
 
\t <collection collection='rootList' list='list' coldisplay='"code"' colfrom='"parent"' colto='"id"'></collection> 
 
    </div> 
 
</body> 
 
</html>

灵感来自https://toddmotto.com/everything-about-custom-filters-in-angular-js/

+0

完美答案! –

+0

有一个问题,我尝试检查元素,TANK和CHEM在span元素内。 span元素来自哪里? –

+0

如果你不想要这种行为,只需添加'transclude:true'(编辑样本) –

0

解决您的问题,我建议一些变化。首先,因为您从API获取数据,我们需要修改格式以获得更合理的结构。像下面

[{ 
    id: 1, 
    code: "TANK", 
    tree_id: 1, 
    parent: null, 
    children: [{ 
    id: 3, 
    code: "CHEM", 
    tree_id: 1, 
    parent: 1, 
    children: [{ 
     id: 9, 
     code: "PROD", 
     tree_id: 1, 
     parent: 3 
    }] 
    }, { 
    id: 2, 
    code: "OIL", 
    tree_id: 1, 
    parent: 1, 
    }] 
}, { 
    id: 4, 
    code: "BULK", 
    tree_id: 2, 
    parent: null, 
    children: [{ 
    id: 5, 
    code: "LOG", 
    tree_id: 2, 
    parent: 4, 
    }] 
}] 

为此,我们需要编写函数如下

var createObject = function(json) { 
    return { 
     id: json.id, 
     code: json.code, 
     tree_id: json.tree_id, 
     parent: json.parent, 
     children: [] 
    } 
}; 

var processList = function(temporaryObj) { 

    for (var i = 0; i < list.length; i++) { 
     if (list[i].parent === temporaryObj.id) { 
      temporaryObj.children.push(processList(createObject(list[i]))); 
     } 
    } 

    return temporaryObj; 
}; 

var convertList = function(list) { 

    var temp = []; 
    for (var i = 0; i < list.length; i++) { 

     if (list[i].level === 0) { 
      temp.push(processList(createObject(list[i]))); 
     } 

    } 

    return temp; 
}; 

var newList = convertList(list_from_api); 

并在此之后,我们需要创建一个递归指令东西要打印的内容在UI

app.directive("tree", ['$compile', '$templateCache', function($compile, $templateCache) { 
    return { 
    type: "E", 
    scope: { 
     list: "=" 
    }, 
    link: function(scope, element, attrs) { 
     element.replaceWith($compile($templateCache.get('tree.html'))(scope)); 
    } 
    } 
}]); 

哪里树.html如下

<ul ng-if="list.length > 0"> 
    <li ng-repeat="item in list"> 
     <span>{{ item.code }}</span> 
     <tree list="item.children"></tree> 
    </li> 
</ul> 

你可以参考这个plunkr链接了解更多详情 https://plnkr.co/edit/8TtgFfgUQd73Du47b7XB?p=preview