FirebaseExtended / angularfire

AngularJS bindings for Firebase
MIT License
2.73k stars 631 forks source link

question: example syntax for binding firebase to a factory #119

Closed beebase closed 11 years ago

beebase commented 11 years ago

I'd like to bind a firebase to a factory instead of a controller $scope. Is there an example somewhere?

(roughly something like this ? except that $scope is not present in a factory) var app = angular.module('myapp',['firebase']) .factory('Items', function( angularFire){

    var items = [];
    var refItems = new Firebase('https://sketch.beebaseio.com/items');

    angularFire( refItems, 'items');

    return items;
}) 
johnsoftek commented 11 years ago

angularFire needs a scope object to set a watcher on the local variable. You can create your own scope from $rootScope. I would be curious to see if this would work:

var scope = $rootScope.$new();
scope.items = [];
var refItems = new Firebase('https://sketch.beebaseio.com/items');

angularFire( refItems, scope, 'items');

return scope.items;
beebase commented 11 years ago

Unfortunately that didn't work. img320 img321

johnsoftek commented 11 years ago

I'm puzzled by the server address: sketch.beebaseio.com. Not ...firebaseio.com?

beebase commented 11 years ago

yep..that was nonsense...changed to firebasio.com No errors anymore, but still an empty items array. In the meantime, I'm going to catch up some reading on angular scopes cause I'm a newbie. img328

johnsoftek commented 11 years ago

scope.items is being set correctly but this line in angularfire.js changes the scope.items object reference every time data is retrieved from the Firebase location, including the first retrieval:

    this._parse(name).assign($scope, angular.copy(val));

. So, the array reference you return from the factory never refers to data returned from Firebase. You can make it work if you return the scope variable (say as ItemModel ) and then reference ItemModel.items in the view.

angular.module("app",['firebase'])

.factory("ItemModel", function($rootScope,angularFire) {
  var scope = $rootScope.$new(),
      url = 'https://angularFireTests.firebaseio-demo.com/issue119';
  scope.items = [];
  var promise = angularFire(new Firebase(url).child('items'), scope, 'items');
  return scope;
})

.controller("ItemsCtrl", function($scope, $timeout, ItemModel) {
  $scope.ItemModel = ItemModel;
  // reference item in ItemModel.items in the view
});

Have you thought of using angularFireCollection instead of angularFire? The collection object reference never changes.

angular.module("app",['firebase'])

.factory("Items", function($rootScope,angularFireCollection) {
  var scope = $rootScope.$new(),
      url = 'https://angularFireTests.firebaseio-demo.com/issue119';
  scope.items = angularFireCollection(new Firebase(url).child('items'));
  return scope.items;
})

.controller("ItemsCtrl", function($scope, $timeout, Items) {
  $scope.items = Items;
})
anantn commented 11 years ago

Either workarounds as proposed by @johnsoftek should work - please re-open if you're still having trouble!

beebase commented 11 years ago

Works perfectly, thanks a lot!

angularFire based: img414

angularFireCollection based: img416