Waseem
Waseem

Reputation: 8402

How do I access individual elements in $FirebaseArray without waiting for it to $loaded?

I request some data from Firebase using AngularFire like below.

$rootScope.userTags = $firebase($fbCurrent.child('tags')).$asArray();

On logging this data in following ways I get the outputs as in the image below. So,

console.log($rootScope.userTags);
console.log($rootScope.userTags[0]);
$rootScope.userTags.$loaded().then(function () {
  console.log($rootScope.userTags[0]);
});

enter image description here

In first log statement you can notice an $FirebaseArray object with five elements. In second log statement when I try to access one of the elements, I get undefined although you can clearly see those elements in the un$loaded array. Now in the last log statement, calling $loaded lets me access those elements without any issues.

Why does it behave this way? And is there a way I can access those elements, since those are already there, without calling $loaded on the array?

Upvotes: 0

Views: 660

Answers (1)

David East
David East

Reputation: 32604

The $asArray() or $asObject() methods are asynchronous actions. The data has to be downloaded from Firebase before it can be accessed. This is just the nature of asynchronous data and not anything specific to Firebase.

The way we handle this issue of asynchrony is through the $loaded promise.

It seems though the real issue here ensuring data is loaded upon instantiation of the controller. You can solve this be resolving the data in the router.

Resolve require a promise to be returned. When the user routes to that page, Angular will not load the page until the promise has been resolved. The data resolved from the promise will injected into the controller.

.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider

      .when('/resolve', {
        templateUrl: 'resolve.html',
        controller: 'ResolveCtrl',

        resolve: {
          // data will be injected into the ResolveCtrl
          data: function($firebase) {
           // resolve requires us to return a promise
           return $firebase(new Firebase('your-firebase')).$asArray().$loaded();
          }
        }

      })
  }
])

Now that we are resolving the data in the route we can access it in our controller.

.controller('ResolveCtrl', function($scope, data) {

  $scope.userTags = data;
  $scope.userTags[0]; // data has been resolved from the promise

});

Upvotes: 2

Related Questions