2013-03-22 157 views
30

我有时会遇到严重的麻烦,理解AngularJS。所以,我有我的控制器一样AngularJS不刷新ngRepeat更新数组时

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

我ngRepeating在我的模板在项目阵列NG重复=“中的项目项”的基本阵列。超级直播迄今。经过几次用户体验操作之后,我想推出一些新的东西到我的阵列中。

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

因此,有50%的时间,新元素被添加到视图中。但另外50%,没有任何反应。这就像超级沮丧; bc如果我把它包装在$ scope中$ apply(),我得到了“$ digest已在进行中”的错误。将它包装到$ timeout中也没有帮助。

当我使用Chrome扩展检查我的元素范围时;我可以看到新的数据在那里,$ scope.items的值是正确的。但是这个观点只是没有把这个添加到DOM中。

谢谢!

+0

您可以在http://jsfiddle.net/ – 2013-03-22 12:42:27

+2

上创建演示程序,它确实与摘要循环有关。我们需要您发布您用来更新数组的代码。 – 2013-03-22 12:48:53

+2

我也遇到这个问题,会喜欢答案! – Samuel 2013-05-22 06:11:57

回答

21

您正在修改角度为$digest周期50%以外的范围。

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

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

如果你不知道,不能够学习,这里是一个巧妙的方法:

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

我相信你应该避免检查'$ scope。$$ phase'。这是内部变量,如果可能的话,你不应该依赖你的代码。最好的解决方案就是使用'$ apply',如果你确信已经没有'$ apply'了,那么你就可以使用'apply'了。这就是为什么我要求可能更新范围的代码。 – 2013-03-22 13:18:06

+0

这不是一个好的代码方式,我同意。然而,它确实有效,'$$ phase'非常稳定可靠;至少它不会意外地破坏你的代码,除了它可以在不同版本之间进行更改。 – 2013-03-22 13:24:13

+0

是的。我已经使用它了。问题是我们不知道这个内部状态控制器是否会在下一个小版本中崩溃。我只是在想,可能有更好的地方安全地放置$ apply。 – 2013-03-22 13:27:39

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。

4

正如UmurKontacı指出的那样,您有时会在摘要循环之外进行模型更改。然而,与其解决这个问题并试图检测您是否处于应用/摘要上下文环境中,我建议您确保不会发生这种情况。

此问题的主要原因是您的函数被称为DOM事件的反应。例如。

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

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

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

然而,有一点需要注意,你必须要知道的:当您触发从代码中的单击事件,您将运行进入消化周期已经在进行的问题。这是你需要$超时的地方。 this question的答案很好地解决了这个问题。