Reputation: 153
I'm trying to get the new Firebase queries working in my factory, but I'm stuck. I want to return the value of 'logo' out of my opponents table, based on the opponent name. I can get the example with console.log
from the Firebase docs running:
function OpponentService($firebase) {
var factory = {};
var _url = 'https://somefirebaseproject.firebaseio.com/opponents';
var _ref = new Firebase(_url);
factory.getLogo = function(opponent) {
_ref.orderByChild('name').equalTo(opponent).on("child_added", function(snapshot){
console.log(snapshot.val().logo);
});
};
return factory;
}
When I call my factory with OpponentService.getLogo(opponentName)
in my controller, I get the correct logo id in my console. But how can I return the value instead of sending it to my console? I want to store it in a variable like this: $scope.opponentLogo = OpponentService.getLogo(opponentName)
. I tried several variations with a return statement like this:
factory.getLogo = function(opponent) {
_ref.orderByChild('name').equalTo(opponent).on("child_added", function(snapshot){
return snapshot.val().logo;
});
};
But apparently I don't fully understand how factories work in Angular, because I get an undefined
. Could it be that the value isn't available yet and I should use a promise in someway? Anyone who can point me in the right direction?
Upvotes: 2
Views: 2111
Reputation: 1926
You're returning the value of logo from the anonymous function inside the Firebase on()
call, but you're not returning anything from getLogo()
.
Returning a promise would be a good way to do this. This is how you retrieve the opponent logo with AngularFire, if there is no guarantee opponentName
will be unique:
// getLogo() returns a promise that you can bind to the UI.
// When loading finishes, the binding will get the opponent's logo value.
factory.getLogo = function (opponentName) {
var opponentsArray = $firebase(_ref.orderByChild('name').equalTo(opponentName)).$asArray();
// $loaded() returns a promise, so we can use the then() method to add
// functionality when the array finishes loading and the promise resolves.
var r = opponentsArray.$loaded().then(function () {
// Now return the logo for the first matching opponent
return opponentsArray[0].logo;
});
return r;
};
If opponentName
is unique, I would rethink the data structure so that you could use the opponentName as the key for opponents. Then you would be guaranteed to get a single opponent and could fetch it with:
var opponent = $firebase(_ref.child(opponentName)).$asObject();
If you're not using AngularFire, you can return a promise using Angular's $q
service. The following should work:
factory.getLogo = function(opponent) {
$q(function (resolve, reject) {
function successCallback(snapshot) {
resolve(snapshot.val().logo);
};
function cancelCallback(error) {
reject(error); // pass along the error object
};
_ref.orderByChild('name').equalTo(opponent)
.on("child_added", successCallback, cancelCallback);
});
};
You can assign the result of getLogo()
to a scope variable, and bindings will update in the UI when Firebase returns the value.
Upvotes: 5