2016-05-17 64 views
7

我有這樣的分層數據:角追加parent屬性值

[ 
    { 
     "children":[ 
      { 
       "children":[...], 
       [...] 
      }, 
      { 
       "children":[...], 
       [...] 
      }, 
     ], 
     [...] 
    } 
] 

我想通過扁平化的數據建立樹狀網格。我使用以下指令:

app.directive('tree', function (hierarchyService, logger, $timeout) { 
    return { 
     scope: { 
      data: '=' 
     }, 
     restrict: 'E', 
     replace: true, 
     template: '<div>' + 
      '<table class="table table-striped table-hover">' + 
      ' <thead>' + 
      '  <tr>' + 
      '   <th class="col-md-6">Account name</th>' + 
      '  </tr>' + 
      '  </thead>' + 
      '  <tbody><tr collection data="data" /></tbody>' + 
      ' </table>' + 
      '</div>' 
    }; 
}); 

app.directive('collection', function() { 
    return { 
     restrict: "A", 
     replace: true, 
     scope: { 
      data: '=', 
      depth: '@' 
     }, 
     template: '<member ng-repeat="member in data" member="member" depth="{{depth}}" />', 
     link: function (scope, element, attrs) { 
      scope.depth = parseInt(scope.depth || 0); 
     } 
    } 
}); 

app.directive('member', function($compile) { 
    return { 
     restrict: "E", 
     replace: true, 
     scope: { 
      depth: '@', 
      member: '=' 
     }, 
     template: '<tr ng-class="{selected: member.selected}">' + 
      '<td>' + 
      ' <span ng-show="depth > 0" style="width: {{depth * 16}}px; display: inline-block;"></span> {{member.name}}' + 
      '</td>' + 
      '</tr>', 
     link: function (scope, element, attrs) { 
      scope.depth = parseInt(scope.depth || 0); 

      if (angular.isArray(scope.member.children) && scope.member.children.length > 0) { 
       var el = angular.element('<tr collection data="member.children" depth="{{newDepth}}" />'); 
       scope.depth = parseInt(scope.depth || 0); 
       scope.newDepth = scope.depth + 1; 
       $compile(el)(scope); 

       // Flatten hierarchy, by appending el to parent 
       element.parent().append(el); 
      } 
     } 
    } 
}); 

的問題是,在收集從link方法添加,從父範圍depth附加到newDepth。因此,級別3節點的depth的值爲depth="3 2 1 "

如何禁用繼承depth

我也注意到,當我在collectionmember指令中將replace更改爲false時,深度按預期工作,但是HTML無效。

+0

你能爲你的情況下,plunker或小提琴? –

+0

@SpartakLalaj您在這裏:https://plnkr.co/edit/CE2z5WeU41H4qJQQ73B7?p=preview – Krzysztof

+0

我刪除了深度屬性,並在集合中聲明瞭等號並且似乎這些數字是正確的。試試看看這是否是正確的結果! –

回答

0

看來,使用相同的作用域的子節點,導致奇怪的連接。解決這個問題非常簡單,因爲事實證明 - 每個孩子都需要新的子範圍。鏈接功能看起來就像這樣:

link: function (scope, element, attrs) { 
    if (angular.isArray(scope.member.children) && scope.member.children.length > 0) { 
     // Create isolated child scope, pass `scope` as parent 
     var childScope = scope.$new(true, scope); 
     childScope.depth = parseInt(scope.depth || 0) + 1; 
     childScope.member = scope.member; 

     var el = angular.element('<tr collection data="member.children" depth="{{depth}}" />'); 

     // use child scope 
     $compile(el)(childScope); 

     // Flatten hierarchy, by appending el to parent 
     element.after(el); 
    } 
} 

普拉克:https://plnkr.co/edit/xhJwfV?p=preview

我還發現其他地方的SO和API,即replace被棄用,因此,它實際上should't使用。因此,沒有取代它可以是這樣的:

app.directive('tree', function() { 
    return { 
     restrict: 'E', 
     template: '<div>' + 
      '<table class="table table-striped table-hover">' + 
      ' <thead>' + 
      '  <tr>' + 
      '   <th class="col-md-6">Account name</th>' + 
      '   <th class="col-md-1">Depth</th>' + 
      '  </tr>' + 
      '  </thead>' + 
      '  <tbody row data="data"></tbody>' + 
      ' </table>' + 
      '</div>', 
     link: function (scope, element, attrs) { 
      scope.data = [ 
       { 
       name: 'Root', 
       children: [ 
        { 
        name: 'Level 1', 
        children: [ 
         { 
         name: 'Level 2', 
         children: [ 
          {name: "Level 3"}, 
          {name: "Level 3 -1"} 
         ] 
         } 
        ] 
        }, 
        { 
        "name": "Level 1-1" 
        } 
       ] 
       } 
      ]; 
     } 
    }; 
}); 

app.directive('row', function() { 
    return { 
     restrict: "A", 
     scope: { 
      data: '=', 
      depth: '@' 
     }, 
     template: '<tr cells ng-repeat="member in data" member="member" />', 
     link: function (scope, element, attrs) { 
      scope.depth = parseInt(scope.depth || 0); 
     } 
    } 
}); 

app.directive('cells', function($compile) { 
    return { 
     restrict: "A", 
     scope: { 
      data: '=', 
      depth: '@', 
      member: '=' 
     }, 
     template: //'<tr ng-class="{selected: member.selected}">' + 
      '<td>' + 
      ' <span ng-show="depth > 0" style="width: {{depth * 16}}px; display: inline-block;"></span> {{member.name}}' + 
      '</td>' + 
      '<td>{{depth}}</td>', 
      //'</tr>', 
     link: function (scope, element, attrs) { 
      if (scope.member && angular.isArray(scope.member.children) && scope.member.children.length > 0) { 
       var childScope = scope.$new(true); 
       childScope.depth = parseInt(scope.depth || 0) + 1; 
       childScope.data = scope.member.children; 

       var el = angular.element('<tr cells ng-repeat="member in data" member="member" depth="{{depth}}" />'); 

       $compile(el)(childScope); 

       // Flatten hierarchy, by appending el to parent 
       element.after(el); 
      } 
     } 
    } 
}); 

Plunker:https://plnkr.co/edit/j3YcuQ?p=preview

2

有時更簡單的解決方案更好。最好將樹狀結構平坦化,然後使用ng-repeat迭代新結構。 https://plnkr.co/edit/CiFGZYi6NdH8ZFDiAyPz?p=preview

更簡單的代碼。沒有必要使所有這些難以理解的指令。你也不應該使用替換指令,因爲它是deprecated

要動態設置樣式,您應該使用ng-style指令。

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

app.factory('treeFlatting', function() { 
    function flattenTree(tree, depth) { 
    depth = depth || 0; 

    return tree.reduce(function (rows, node) { 
     var row = { 
     name: node.name, 
     depth: depth, 
     }; 
     var childrenRows = angular.isArray(node.children) ? 
     flattenTree(node.children, depth + 1) : []; 

     return rows.concat(row, childrenRows); 
    }, []); 
    } 

    return flattenTree; 
}); 

app.directive('tree', function (treeFlatting) { 
    return { 
     restrict: 'E', 
     replace: true, 
     template: '<div>' + 
      '<table class="table table-striped table-hover">' + 
      ' <thead>' + 
      '  <tr>' + 
      '   <th class="col-md-6">Account name</th>' + 
      '   <th class="col-md-1">Depth</th>' + 
      '  </tr>' + 
      '  </thead>' + 
      '  <tbody>'+ 
      '   <tr ng-repeat="row in rows">'+ 
      '    <td ng-style="{\'padding-left\': (16 * row.depth) + \'px\'}">{{row.name}}</td>'+ 
      '    <td>{{row.depth}}</td>'+ 
      '   </tr>'+ 
      '  </tbody>' + 
      ' </table>' + 
      '</div>', 
     link: function (scope, element, attrs) { 
      scope.data = [ 
       { 
       name: 'Root', 
       children: [ 
        { 
        name: 'Level 1', 
        children: [ 
         { 
         name: 'Level 2' 
         } 
        ] 
        } 
       ] 
       } 
      ]; 

      scope.rows = treeFlatting(scope.data).filter(function (row) { 
      return row.depth > 0; 
      }); 
     } 
    }; 
}); 
+0

我也可以使用專用的樹組件,但這不是重點。這種行爲至少在我看來是奇怪的,我想現在如果它的意圖(並可以以某種方式禁用),或者如果它是一個錯誤。最奇怪的是,當我將替換標誌切換爲假時,它可以正常工作(但標記會被搞亂)。 – Krzysztof

+0

我沒有看到它,但我敢打賭,問題是使用'@'和字符串連接。順便說一句。你爲什麼以這樣一種奇怪的方式做到這一點? – sielakos

+0

我只是在玩角,而這種行爲並不是我所期望的。由於我遇到這個問題,我想知道解決方案。 – Krzysztof