【问题标题】:Using data from an ng-repeat in a function在函数中使用来自 ng-repeat 的数据
【发布时间】:2015-03-27 22:17:51
【问题描述】:

我是 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-repeat 视图的函数的方法不正确?如果是这样,AngularJS 的正确方法是什么?

【问题讨论】:

  • 这是您的代码中的错字还是不正确? - res.worker.tips.lengh
  • 为什么不先计算每个工作人员在控制器负载上的小费,然后执行getWorkersTip(id) 之类的操作,而不是在每次单击时发送请求?

标签: angularjs coffeescript angularjs-ng-repeat


【解决方案1】:

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

你应该修改一下这段代码:

{{ getTipCount(worker.id) }}

这样的:

{{ workertipscount }}

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

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

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

<!-- 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 调用中加载一组工作人员,因此您可能会遇到这样的情况:

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

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

附带说明一下,返回服务器的次数如此之多是非常无用的,尤其是当您有大量集合时,因为浏览器将您限制为对同一域的 6 个并发请求。 p>

您可能会考虑重新设计您的 API,该 API 首先返回工作人员列表,以便简单地继续并包含他们的小费计数数据。

说明:

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

$digest 循环遍历$scope 中的每个值,并根据已创建的$watchers 将其与旧值进行比较。任何时候你使用{{ }} 语法,你都在创建一个观察者。

Angular 一直执行这个循环,直到没有检测到任何变化。

在函数表达式的情况下,Angular 无法在不执行函数的情况下知道值是否发生了变化...在这种情况下,它会导致脏状态。因此,这个过程会无限重复,直到 10 次迭代的故障保护启动并且 Angular 呕吐。

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

【讨论】:

  • 感谢@Josh,这是非常好的信息。一件事是我在代码中的 ng-click 仅作为测试,是否可以在不使用 ng-click 的情况下执行您所描述的操作?
  • 因为我需要在重复的每次迭代中从 Worker 中提取 id 并将其传递给函数,但如果我不应该在 ng-repeat 中调用函数,那么什么是最好的如何在 Angular 中做到这一点?
猜你喜欢
  • 2014-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多