Firebase's AngularFire in an AngularJS service

All we need is an easy explanation of the problem, so here it is.

The best way of handling Firebase in AngularJS surely has to be from within a service, so it’s available to all Controllers across the App.

I just can’t get it to work! … I first tried using angularFire(new Firebase(url)), hoping I could bind to the service’s scope, but Angular complains that it cannot $watch it.

So I tried angularFireCollection instead like this:

app.factory('myService', function myService(angularFireCollection) {
    var url = 'https://myfirebase.firebaseio.com';
    return {
        getAll: function(path) {
            var ref = angularFireCollection(new Firebase(url + '/' + path));
            console.log(ref);
            return ref;
        },
        ...
    };
});

However, the angularFireCollection is an Object containing a load of methods etc. if I bind it to a controller $scope I just get garbage. It also complains that it can’t call the Firebase functions before I try to use them (e.g. Error: Firebase.push failed: second argument must be a valid function.)… anyone got any ideas where I’m going wrong?

See this PLUNKER

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

If you want to encapsulate some of the functionality into a service, consider keeping the returned ref in state of the service. I expanded on your plunker. It seems to mostly do what you were trying for.

http://plnkr.co/edit/Uf2fB0

Method 2

Jeff answered the question correctly … I’m just posting a further development on Jeff’s example for those who are interested.

I have abstracted the Firebase service creation, so you can dynamically create an instance of whatever Firebase service you want:-

var registerFirebaseService = function (serviceName) {
    app.factory(serviceName, function (angularFire) {
        var _url = null;
        var _ref = null;

        return {
            init: function (url) {
                _url = url;
                _ref = new Firebase(_url);
            },
            setToScope: function (scope, localScopeVarName) {
                angularFire(_ref, scope, localScopeVarName);
            }
        };
    });
};

You first create an instance of the service as follows

registerFirebaseService('itemsService'); // create itemsService instance

Then you can inject the itemsService service into your controllers. The instance is initialised using your Firebase URL e.g.

itemsService.init('https://firebase.firebaseio.com/' + userId + '/items');

The Firebase can now be bound to your controller e.g.

itemsService.setToScope($scope, 'items');

adapted PLUNKER

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply