AngularJS在更新数组时没有刷新ngRepeat

时间:2013-03-22 12:39:37

标签: javascript angularjs angularjs-ng-repeat

我有时会对AngularJS有严重的麻烦。所以我的控制器中有一个基本数组,如

$scope.items = ["a","b","c"]

我正在我的模板中重复项目数组ng-repeat =“item in items”。到目前为止超级直播。经过几次UX操作后,我想将一些新东西推送到我的阵列。

 $scope.items.push("something");

因此,50%的时间,新元素被添加到视图中。但其他50%,没有任何反应。这就像超级沮丧; bc如果我把它包装在$ scope。$ apply()中,我得到了“$ digest in progress”错误。将其包装到$ timeout也无济于事。

当我使用Chrome扩展程序检查我的元素范围时;我可以看到新数据存在且$ scope.items值是正确的。但是视图并没有考虑将其添加到DOM中。

谢谢!

3 个答案:

答案 0 :(得分:21)

您正在50%的时间内在范围$digest周期之外修改范围。

如果有回调不是来自angularjs; (可能是jquery)。您需要致电$apply以强制进行$digest周期。 但是,您无法在$apply周期内拨打$digest,因为您所做的每项更改都会自动反映出来。

您需要知道回调何时不是来自角度,并且应该仅在此时调用$apply

如果您不知道并且无法学习,这是一个巧妙的技巧:

var applyFn = function () {
    $scope.someProp = "123";
};
if ($scope.$$phase) { // most of the time it is "$digest"
    applyFn();
} else {
    $scope.$apply(applyFn);
}

答案 1 :(得分:4)

正如UmurKontacı所指出的,你有时会在摘要周期之外进行模型更改。但是,我建议您确保不会发生这种情况,而不是解决此问题并尝试检测您是否处于应用/摘要上下文中。

此问题的主要原因是您的函数被调用为对DOM事件的反应。 E.g。

jQuery('.some-element').click(function() { seeminglyProblematicCode() })

这是你的$ apply()需要去的地方,而不是在函数内。否则,您的整个代码迟早会被这些区别所困扰。假设在此事件处理程序的上下文中有一个范围,您可以编写:

jQuery('.some-element').click(function() { 
    $scope.$apply(function() { seeminglyProblematicCode() })
})

但是,您必须注意一个警告:当您从代码中触发单击事件时,您将遇到摘要周期已在进行中的问题。这是你需要$ timeout的地方。 ApnsServiceBuilder withProxy(java.net.Proxy)的答案很好地解决了这个问题。

答案 2 :(得分:0)

我遇到了同样的问题,我的修复方法是观察在嵌套指令中调用哪些控制器。

# Parent Controller
app.controller 'storeController', ($scope, products) ->

  $scope.cart = ["chicken", "pizza"]
  $scope.addToCart = (item) ->
    $scope.cart.push item

  # from service
  products.get().then (items) ->
    $scope.products = items

# Parent Directives
app.directive 'storeContainer', ($scope, config) ->
  restrict: 'E'
  templatUrl: 'store-container.html'
  controller: 'storeController'

# Nested Directive
app.directive 'storeFront', ($scope, config) ->
  restrict: 'E'
  templatUrl: 'store-front.html'
  controller: 'storeController'

# Parent Template templates/directives/store-container.html
<div ng-repeat="item in cart">{{ item }}</div>
<strore-front></store-front>

# Nested Template templates/directives/store-front.html
<ul ng-repeat="item in products">
  <li ng-click"addToCart(item)">{{ item }}</li>
</ul>

这里的错误是嵌套指令在原型链中创建第二个控制器(storeController的副本),父模板无权访问。解决方案如下所示写嵌套控制器:

# Nested Directive
app.directive 'storeFront', ($scope, config) ->
  restrict: 'E'
  templatUrl: 'store-front.html'

有更好的方法来创建继承链,但这将解决许多人学习AngularJS的问题。