使用函数中ng-repeat的数据

时间:2015-02-10 13:38:08

标签: angularjs coffeescript angularjs-ng-repeat

我是AngularJS的新手,我正在尝试更多地了解ng-repeat的可能性。我已经整理了一些代码来尝试学习更多但是我遇到了一些我不理解的问题。

以下是代码:

HTML:

<ul class="list-unstyled">
    <li ng-repeat="worker in workers">
        <section class="well col-md-6 col-md-offset-3">
            <h1 class="h3 col-md-6 text-right" style="margin-top: 0"><a>{{worker.worker_name}} {{ getTipCount(worker.id) }}</a></h1>
        </section>
    </li>
</ul>

在我的控制器中:

$scope.getTipCount = (workerId) ->
      WorkerTips = $resource("/workers/#{workerId}", { workerId: "@id", format: 'json' })
      json = WorkerTips .get ((res) ->
         $scope.workertipscount = res.worker.tips.lengh
      )

在JSON中,每个工作者对象都有一系列提示,我想要做的是获取每个工作者有多少提示的计数。要做到这一点,我需要通过ng-repeat从工作者那里获取id,然后将其传递给一个函数,然后从JSON中获取技巧并将其显示在页面上。

然而,当我尝试这样做时,看起来页面进入无限循环,我收到以下错误:

  

错误:[$ rootScope:infdig] 10 $ digest()迭代达成。中止!

所以我猜测我的方法是从ng-repeat中的元素中提取信息,然后将它发送到也被发送到ng-repeats视图的函数是不正确的?如果是这样,AngularJS的正确方法是什么?

1 个答案:

答案 0 :(得分:5)

问题是你正在调用一个函数,这将导致修改$scope上的绑定值,然后再次执行该函数......等等......

你应该改变这一点代码:

{{ getTipCount(worker.id) }}

对于这样的事情:

{{ workertipscount }}

此外,这似乎是您在此处设置的全局变量:

$scope.workertipscount = res.worker.tips.lengh

相反,您可以将其直接设置到worker对象本身:

<!-- Send in the entire worker object -->
ng-click="getTipCount(worker)"

//Now you can set properties directly on
// the worker
$scope.getTipCount = (worker) ->
      WorkerTips = $resource("/workers/#{worker.id}", 
          { workerId: "@id", format: 'json' })

      json = WorkerTips.get ((res) ->
         worker.tipCount = res.worker.tips.length;
      )

<!-- And then just bind to that property -->
{{ worker.tipCount }}

这只是一个建议,你肯定不必遵循,但我发现这种方法让生活变得更轻松。

<强>更新

根据您在下方发表的评论,我建议您在收集时简单预先计算此信息。我假设您正在从AJAX调用中加载一组worker,所以你可以这样:

someMethodToGetWorkers()
  .then(function(workers){
     $scope.workers = workers;
  })
  .then(function(){
     angular.forEach($scope.workers, function(worker){
        //Make call to populate worker tips
     });
  });

这将填充每个工作人员的提示,如果您将它们保存到工作者对象本身,那么您可以在ng-repeat中直接绑定到它,如上所述。

作为旁注,让这么多次回到服务器是非常有用的,特别是如果你有一个大的集合,因为浏览器会限制你同一个域的6个并发请求。

您可能会考虑重新编写返回工作人员列表的API,以便继续操作并包含其提示计数的数据。

<强>解释

Angular uses dirty checking。这意味着它将旧值与新值进行比较,以确定是否应该执行操作。它通过$digest循环来实现这一点。

$digest循环旋转$scope中的每个值,并根据创建的$watchers将其与旧值进行比较。每次使用{{ }}语法时,您都会创建一个观察者。

Angular会一直执行此循环,直到没有检测到更改。

在函数表达式的情况下,Angular无法在不执行函数的情况下知道值是否已更改 ...在这种情况下,它会导致脏状态。因此,这个过程无限重复,直到10次迭代的失败保障开始和Angular pukes。

一般来说,最好避免像{{ foo() }}这样的函数表达式,因为它们将在$digest的每个循环中执行。