AngularJS: traversing nested arrays

后端 未结 2 1281
我寻月下人不归
我寻月下人不归 2021-02-06 15:06

I am working with a nested array with the structure...

$scope.items = [{attr1: val1, 
  attr2: val2,
  items: [{
     attr1: val1, 
     attr2: val2,
     items:         


        
相关标签:
2条回答
  • 2021-02-06 15:23

    Before rendering data, you can make some preparations. One recursive run over your data to set level value and a link to the parent to each item. Example with your data using LoDash:

    var level = 0;
    _.each($scope.items, function(item){recursive(item, level)});
    
    function recursive(item, level){
        item.level = level;
        _.each(item.items, function(innerItem){
            innerItem.parent = item;
            recursive(innerItem, level+1);
        });
    }
    

    So now you can easily get parent and siblings of each item.

    find an item's parent -> item.parent

    find an item's sibling -> item.parent.items[i]

    make counts of siblings -> item.parent.items.length

    find out how many levels deep an item is nested -> item.level

    insert or delete items at any level of the nest (move operation example) ->

    newParent.items.push(item);
    _.remove(item.parent.items, function(child){return child == item;});
    

    The only minus of this approach which i met - you can not easily clone whole tree without going into endless recursion. But you can make custom cloning function which will not copy links.

    0 讨论(0)
  • 2021-02-06 15:26

    If you alias item.items in the ng-repeat expression, angular will keep track of the array structure and hierarchical relationships for you.

    <div ng-repeat="item in items = item.items">
    

    Then, operations on the tree can simply pass in the item, the $index, or the array of items - without knowledge of the full array structure:

      <button ng-click="addItem(item)">Add to my items</button>
      <button ng-click="addSiblingItem(items, $index)">Add a sibling item</button>
      <button ng-click="deleteMe(items, $index)">Delete Me</button>
    

    js:

    $scope.addItem = function(item) {
      item.items.push({
        attr1: 'my new - attr1',
        attr2: 'my new - attr2',
        items: []
      });
    }
    $scope.addSiblingItem = function(items, position) {
      items.splice(position + 1, 0, {
        attr1: 'sibling - new attr1',
        attr2: 'sibling - new attr2',
        items: []
      });
    }
    $scope.deleteMe = function(items, position) {
      items.splice(position, 1);
    }
    

    To get the number of siblings, you can refer to items.length:

    <h3>Item #{{$index + 1}} of {{items.length}}</h3>
    

    If you really need to access the parent siblings from child items, you can add another alias for parent = item and add it to the item using ng-init:

    ng-repeat="item in items = (parent = item).items" ng-init="item.parent = parent"
    

    Then you have access to the grandparent (parent.parent) and its items (the parent siblings).

    In addition, you can keep track of the current nest level using ng-init:

    ng-init="item.parent = parent; item.level = parent.level + 1"
    

    Here is a working demo: http://plnkr.co/xKSwHAUdXcGZcwHTDmiv

    0 讨论(0)
提交回复
热议问题