Search code examples
angularjsfirebasefirebase-realtime-databaseangularfire

how to retrieve data nested in two collections from firebase with angular


I'm new in Angular - Firebase development, and I am having problems to understand how to retrieve data nested in two collections. I have a collection named "Orders", which includes a field call "auth", which is the user ID, and I have another collection that is the "User Profile", where its $id is the value of "auth". Inside the User Profile I have a field named roomNumber, and it's content I that I want to retrieve every time I read, in ng-repeat of the Orders.

In my view I was trying to do something like this:

<tr ng-repeat="item in items | filter: searchKeyword ">
  <td align="left">{{item.$id}} -  {{roomNumber(item.$id)}}</td></tr>

roomNumber is a function in my controller

$scope.roomNumber = function(id) {
 var rootRef = new Firebase("https://xxxx-fire-yyyy.firebaseio.com/userProfile"+ '/' + id);
  $scope.userdet = $firebaseArray(rootRef);
  rootRef.on("value", function(rootSnapshot) {
        var key = rootSnapshot.key();
        var childKey = rootSnapshot.child("room").val();
        console.log("room ", childKey)
    });
 return childKey
  }

When I run this code and see results in my js console, strange things happened:

  1. It repeat a lot of times
  2. I can never get the childKey value

I have been reading Firebase documentation, but really I do not understand how to do this "silly" thing, does anybody give me a tip of how to do it?

enter image description here


Solution

  • When you bind a function to the $scope and call it within the html it expects to get an answer back right away when called. So when you query firebase and it takes its sweet time getting you back an answer, angularjs has already gotten an answer of undefined from the function.

    So what is happening is that you are registering a callback when you provide the function to rootRef.on and then right after you register the callback you are returning the value of childKey. Unfortunately, childKey only gets set by the callback function (which firebase hasn't executed yet). Therefore angularjs gets an answer of undefined from your roomNumber function.

    In order to make this work, you are going to have to get the room numbers beforehand and then probably add them to each of your items in $scope.items then use

    <td align="left">{{item.$id}} -  {{item.room}}</td></tr>
    

    instead of

    <td align="left">{{item.$id}} -  {{roomNumber(item.$id)}}</td></tr>
    

    To load all the room numbers you could call some function like this one after $scope.items has loaded

    for (var i = 0; i < $scope.items.length; i++) {
        var rootRef = new Firebase("https://xxxx-fire-yyyy.firebaseio.com/userProfile"+ '/' + $scope.items[i].$id);
        $scope.userdet = $firebaseArray(rootRef);
        rootRef.on("value", function(rootSnapshot) {
            var key = rootSnapshot.key();
            var childKey = rootSnapshot.val().room;
            $scope.items[i].room = childKey;
        });
    }
    

    It would change each of the items to have a reference to the room. Unfortunately, that list wouldn't update as the data updates, so the better solution would be to do that same query in whatever function was getting your items from the server and add the room to each item as it was being added to the items list.