0

I am using AngularJS and angularFire to show a list of my tasks:

<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/

Code is very simple: I bind a 'site' object to my Firebase DB. The object contains a list of ID of relevant tools. Then I load every tool in the $scope.tools variable and use ng-repeat to show them in the UI. However, every time I push a new entry into my $scope.tools - the DOM is not updated. I have to call $scope.$apply to trigger digest after every push - see commented out line 18 and then it works.

It's really strange since I sow this several times now and only with scope variables bound with angularFire.

Can anyone explain this? Am I doing anything wrong?

4 Answers 4

2

I am not sure about the Firebase once method as how it work, but it seems like it is making changes to model outside of Angular context in it's callback and hence you need $scope.$apply.

In anuglar services like $http ,$resource, and $timeout internally call $scope.$apply so that you don't need to call it on the callback. If the Firebase system provides a method replacement for once which internally does apply or returns a promise, you can very well skip call to apply method again and again.

Sign up to request clarification or add additional context in comments.

2 Comments

Worth noting that if he does need to use $apply it should be $scope.$apply(function() { //do stuff }); ref docs.angularjs.org/api/ng.$rootScope.Scope
Yes, you're right, the change is outside the angular scope and is being applied by a third-party library.
2

Because you change the scope outside of AngularJS, you must use $scope.$apply() to inform Angular about the scope changes. That is a common way to handle that. To use the error handling of AngularJS i would wrap the code in a callback function like:

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

Comments

0

As tschiela says, you need to wrap the function. I use $timeout. So...

<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());
      })
});

Comments

0

To update scopes when you change them, you need to use the factory angularFireCollection of angularFire. Otherwise you are just calling a javascript class wich won't update scopes until $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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.