Reputation: 309
I have been playing around with AngularFire for a few days now, and I'm wondering if I might just be trying what is ultimately a bad use-case for it. I will be doing real-time chat/presence on my site, so that part is useful. This piece I'm working on, though - I dunno.
So I have a registration form. When users register they have to choose a color from a drop down list. I have the list stored in an array in Firebase.
I am trying to maintain a fairly strict MVC setup, so I have each controller in its own file, as well as each corresponding service. Previous angular apps I have written used the structure and it has worked well, until now.
What I can't figure out is the correct way to simply read back the list and populate it into the dropdown.
In previous angular apps, it was just straight up something like:
return $resource(URL + /colors);
So in AngularFire, I was using basically this, which is working, buuuuutttt:
getColors: function($scope) {
syncData('usergen/colors').$bind($scope, 'colorsRaw').then(function() {
var keys = $scope.colorsRaw.$getIndex();
angular.forEach(keys, function(key) {
var color = {label: $scope.colorsRaw[key], value: $scope.colorsRaw[key]};
$scope.data.colors.push(color);
});
$scope.data.color = $scope.data.colors[Math.floor(Math.random() * $scope.data.colors.length)];
});
}
Now of course what I absolutely HATE about it: why am I having to pass $scope around like that? I can't seem to just have getColor() return a regular array of {name: "Blue", value: "Blue"} objects. Not only do I have to pass $scope around, I can't set the drop down to a random value unless I do it in the service. Bad bad bad. I don't want to pass the Ctrl $scope into the service at all and I certainly don't want to be updating Ctrl $scope variables from the service.
So what on earth am I missing here? Firebase seems pretty well developed, so I'm sure it's my complete lack of understanding. I worked through all the chat examples and tutorials and things, but there's nothing quite like what I'm trying to do here.
So is there a way to have a separate service for Firebase/AngularFire calls which allows me to just return values to my Controller without having to pass in a $scope var?
Thanks.
Upvotes: 4
Views: 418
Reputation: 32604
Now of course what I absolutely HATE about it: why am I having to pass $scope around like that?
A lot people think you have to use $scope
with AngularFire. Not only can you use it without $scope
, it's recommended in most cases.
Using AngularFire in $scope
too much can really slow down your app as well because Angular is now tasked with keeping track of it.
When working AngularFire I usually create my $firebase
bindings on a factory/service level. This way it becomes reusable and easy to maintain. Then I can create simple arrays on my controller's $scope and push when new items are added.
angular.module('app', ['firebase'])
.constant('FBURL', 'https://<your-firebase>.firebaseio.com/')
.service('FbRef', ['FBURL', Firebase])
.factory('Colors', function (FbRef, $firebase, $q) {
var $colors = $firebase(FbRef.child('colors'));
return {
get: function getColors() {
var deferred = $q.defer();
$colors.$on('loaded', function (colors) {
var colorArr = [];
angular.forEach(colors, function (color) {
colorArr.push(color);
});
deferred.resolve(colorArr);
});
return deferred.promise;
},
add: function addColor(color) {
$colors.$add(color);
}
};
})
.controller('RegisterCtrl', function ($scope, Colors) {
$scope.colors = [];
// listen for added colors
// this will grab all of the colors on load
Colors.get().then(function (colors) {
$scope.colors = colors;
var randomIndex = getRandomIndex(0, colors.length - 1);
$scope.current = colors[randomIndex];
});
function getRandomIndex(min, max) {
return Math.floor(Math.random() * max) + min;
}
});
The View is just a simple select with ng-model
and ng-options
.
<select ng-model="current" ng-options="c for c in colors"></select>
Upvotes: 1