user5034511
user5034511

Reputation:

Retrieving Data from AngularFire

I'm trying to retrieve data from Angularfire using a service, and then setting the returned value to my scope in my controller.

When I run the code below, I get undefined back for scope.sessions.

SERVICE:

app.factory('sessions', function(){

var refToSessions = new Firebase('myFireBaseURL');
var allSessions = [];

return {
getSessions: function () {
  refToSessions.on("value", function (sessions) {
    allSessions.push(sessions.val());
    return allSessions;
  });
}

}; });

CONTROLLER:

app.controller('SessionsCtrl', ['$scope', '$state', 'Auth', 'sessions', function($scope, $state, Auth, sessions){
  $scope.sessions = sessions.getSessions();

$scope.submitSession = function() {
console.log($scope.sessions);
}
});

Upvotes: 0

Views: 1128

Answers (1)

David East
David East

Reputation: 32604

You're trying to return asynchronous data.

You are logging allSessions to the console before the data has downloaded from Firebase.

Use $firebaseArray from AngularFire.

app.constant('FirebaseUrl', '<my-firebase-url>');
app.service('rootRef', ['FirebaseUrl', Firebase);
app.factory('Sessions', function(rootRef, $firebaseArray){
  var refToSessions = ref.child('sessions');
  return $firebaseArray('sessions');
}

Then injection Sessions into your controller:

app.controller('SessionsCtrl', function($scope, $state, Auth, Sessions){
  $scope.sessions = Sessions; // starts downloading the data

  console.log($scope.sessions); // still empty

  $scope.submitSession = function() { 
    // likely by the time you click here it will be downloaded
    console.log($scope.sessions);
    $scope.sessions.$add({ title: 'new session' });
  };
});

The data starts downloading once it's injected into your controller. When it's downloaded, $firebaseArray knows to trigger $digest, so it appears on the page.

Since you're using ui-router, you can use resolve to make sure the data exists before injecting it into your controller:

app.config(function ($stateProvider) {
  $stateProvider
    .state("session", {
      controller: "SessionsCtrl",
      templateUrl: "views/sessions.html",
      resolve: {
        sessions: function(Sessions) {
          // return a promise that will fulfill the data
          return Sessions.$loaded(); 
        }
      }
    })
});

Now you would change your controller code to this:

app.controller('SessionsCtrl', function($scope, $state, Auth, sessions){
  $scope.sessions = sessions; // data is available since injected by router

  console.log($scope.sessions); // logs the appropriate data

  $scope.submitSession = function() { 
    $scope.sessions.$add({ title: 'new session' });
  };
});

Upvotes: 1

Related Questions