在AngularJS中更新范围变量时,不会触发摘要

时间:2013-08-20 07:40:38

标签: angularjs angularfire

我正在使用AngularJS和angularFire来显示我的任务列表:

<ul ng-repeat="tool in tools">
    <li>{{tool.name}} {{ tool.description}}</li>
</ul>

var toolRef = new Firebase(dbRef + "/tools/" + toolId);
toolRef.once('value', function(snapshot) {
      console.log(angular.toJson(snapshot.val()));
      $scope.tools.push(snapshot.val());
      //$scope.$apply();
});

http://jsfiddle.net/oburakevych/5n9mj/11/

代码非常简单:我将“网站”对象绑定到我的Firebase数据库。该对象包含相关工具的ID列表。然后我加载$ scope.tools变量中的每个工具,并使用ng-repeat在UI中显示它们。 但是,每次我将新条目推送到我的$ scope.tools时 - DOM都不会更新。我必须调用$ scope。$ apply在每次推送后触发摘要 - 见第18行注释然后它可以工作。

这真的很奇怪,因为我现在播种了几次,只有范围变量与angularFire绑定。

任何人都能解释一下吗?我做错了吗?

4 个答案:

答案 0 :(得分:2)

因为您在AngularJS之外更改了范围,所以必须使用$ scope。$ apply()来通知Angular范围更改。这是处理这种情况的常用方法。要使用AngularJS的错误处理,我会将代码包装在回调函数中,如:

$scope.$apply(function(){
  $scope.tools.push(snapshot.val());
});

答案 1 :(得分:1)

我不确定Firebase once方法是如何工作的,但似乎它在回调中对Angular上下文之外的模型进行了更改,因此您需要$scope.$apply

$http$resource$timeout这样的内部服务内部调用$scope.$apply,这样您就无需在回调中调用它。如果Firebase系统为内部确实应用或返回承诺的once提供方法替换,则可以一次又一次跳过调用apply方法。

答案 2 :(得分:0)

正如tschiela所说,你需要包装这个功能。我用$ timeout。所以......

<ul ng-repeat="tool in tools">
    <li>{{tool.name}} {{ tool.description}}</li>
</ul>

var toolRef = new Firebase(dbRef + "/tools/" + toolId);
toolRef.once('value', function(snapshot) {
      $timeout(function() {
          $scope.tools.push(snapshot.val());
      })
});

答案 3 :(得分:0)

要在更改范围时更新范围,您需要使用angularFire的工厂angularFireCollection。否则,您只是调用一个javascript类,它将不会更新范围,直到$apply()

var getTool = function(dbRef,toolId) {
    console.log("Gettingtool ID: " + toolId);
    angularFireCollection(dbRef + "/tools/" + toolId, function(snapshot) {
          console.log(angular.toJson(snapshot.val()));
          $scope.tools.push(snapshot.val());
    });
};

DEMO