在递归ng-repeat中保持相同级别元素的计数

时间:2014-09-26 04:40:25

标签: javascript angularjs recursion

我正在尝试跟踪嵌套树状数组的特定n属性的总和,但是我得不到很好的结果。

Plunkr Here

的JavaScript

var myApp = angular.module('myApp', []);
myApp.directive('layout', function() {

  return {
    templateUrl: 'layout',
    controller: function($scope) {

      // Running total function
      $scope.count = function(n) {
        if (!$scope.total) $scope.total = 0;
        $scope.total += parseInt(n, 10);
        return $scope.total;
      }

      // Tree-like array
      $scope.data = {
        'nodes': [{
          'name': 'layout',
          'n': 1,
          'nodes': [
            {'name': 'box','n': 1}, 
            {'name': 'box','n': 1}, 
            {'name': 'box','n': 1}, 
            {'name': 'box','n': 1}
          ]
        }, {
          'name': 'layout',
          'n': 1,
          'nodes': [
            {'name': 'box','n': 1}, 
            {'name': 'box','n': 1}, 
            {'name': 'box','n': 1}, 
            {'name': 'box','n': 1}
          ]
        }]
      };

    }
  }
});

HTML

<!-- Directive -->
<div layout></div>

<!-- Templates -->
<script type="text/ng-template" id="layout">
<div class="layout" ng-repeat-start="data in data.nodes" ng-include="data.name"></div>
<div ng-repeat-end style="text-align:center;"><i>running total: {{ count(data.n) }}</i></div>
</script>
<script type="text/ng-template" id="box">
<div class="box">.</box>
</script>
  1. 不知怎的,计数似乎从93开始。 - 我已经被@Josep指出这是因为$ digest正在使该函数递归。
  2. 订单错了。
  3. 每次新的递归级别都不会重置计数。
  4. 问题:

    Problem

    预期结果:

    Expected

    我已经尝试了以下方法,没有运气:

    1. 柜台即服务(Plunkr)。 至少数字下降
    2. ng-repeat-startng-repeat-endPlunkr)。我们错过了嵌套计数。
    3. 除了这些事情之外,我一直在修补我是否幸运。老实说,我真的不知道这应该是怎么回事。

      请帮忙解决这个问题?

2 个答案:

答案 0 :(得分:2)

递归ng-include 真的搞砸了我的脑袋,但这似乎做你想要的。

Plunker

<script type="text/ng-template" id="layout">
<div class="layout" ng-repeat-start="data in data.nodes" ng-include="data.name" ng-init="data.t = ($parent.data.nodes[$index -1].t || 0) + data.n"></div>
<div ng-repeat-end style="text-align:center;"><i>running total: {{ data.t }}</i></div>
</script>

每个ng-init我们将此数据的t属性设置为(previous.t + this.n)。我们通过上升一级($ parent)然后使用节点[$ index-1]

来访问前一个

答案 1 :(得分:1)

您不需要count功能,只需执行此操作:

<div class="layout" ng-repeat-start="data in data.nodes" ng-include="data.name"></div>
<div ng-repeat-end style="text-align:center;"><i>running total: {{ ($index+1) }}</i></div>

Example

更新

你不能在ng-repeat表达式中使用这样的函数,因为该函数将在每个$digest周期中得到评估,并且每次都会检索一个不同的值,这将强制$ digest重新评估结果,这将检索不同的值,依此类推,直到它尝试了10次......

如果您需要针对ng-repeat的数据执行此类汇总,我认为您应该创建一个应在ng-repeat(或{ng-repeat-start内使用的自定义过滤器{1}}),filter将检索对象数组的副本,但将聚合信息添加为每个项的新键,以便您可以将其作为迭代项的任何其他属性使用。

这样的事情:ng-repeat-start="data in data.nodes|aggregate:'fieldToAggregate'"

Udate 2

第二个想法是,有一种方法可以使你的count function工作,它非常hacky但它​​有效,改变你的count function,让它看起来像这样:

  $scope.count = function(scope_, n) {
    if (!scope_.hasOwnProperty("__total")){
      if(!scope_.$parent.hasOwnProperty("__count")){
        scope_.$parent.__count=0;
      }
      scope_.$parent.__count+=parseInt(n, 10);
      scope_.__total=scope_.$parent.__count;
    }
    return scope_.__total;
  }

并像这样使用它:

<div ng-repeat-end style="text-align:center;"><i>running total: {{ count(this, data.n) }}</i></div>

Working Examle

这个功能不应该像另一个那样失败,因为每次在重复的项目范围内评估它时,它总会返回相同的结果。