Another Question here,
I am using firebase and angular js, and trying to return data from my database to the console log using this code :
function userCtrl($scope){
$scope.userName="";
$scope.myData = new Firebase ("https://yjyc-signup.firebaseio.com/Entries");
$scope.users={};
$scope.saveUser = function(){
$scope.myData.push({userName: $scope.userName});
$scope.userName="RESET";
};
$scope.myData.on('value', function(snapshot) {
$scope.users = snapshot.val();
console.log("Author: " + $scope.users.name);
});
but the console return "Author: Undefined" although I have a value in my database of a name.
is anybody can help me that would be amazing
When using AngularFire you need to sync the reference before you can get any data from it. Also you're trying to use a Firebase function that doesn't exist for AngularFire as far as I'm aware. Instead try to register a $watch function in your controller and each time that $watch executes you grab the information from the reference. Something like this:
myApp.controller('UserCtrl', ['$scope', function($scope) {
$scope.$watch('watchedExpression', function() {
var ref = new Firebase ("https://yjyc-signup.firebaseio.com/Entries");
var syncedRef = $firebase(ref);
console.log('Author:' + syncedRef.name); //You need to change this path to work with your Firebase tree structure
});
}]);
If you don't want to register a $watch function you can look at the threeway data-binding, you can look at this here in the AngularFire documentation.
Related
i am stuck on the following problem:
i have a select element were the user picks an option.
this option is saved to the localstorage.
now i want to use this stored value as path for a firebasearray.
basically it seems to work but i cant get the firebasearray ref to update without hitting reload.
my firebasearray factory:
.factory("MyFireFactory", ["$firebaseArray", "$localStorage",
function($firebaseArray, $localStorage) {
var ref = firebase.database().ref('demodata/' + $localStorage.selectedoption);
return $firebaseArray(ref);
}
])
After reading the angular docs angular docs if found out that
"...All services in Angular are singletons..." wich basically means if i understood it correctly that they only run once.
Wich in my case meant the i had to move my factory code to the controller so that the data from localstorage can be used.
my now working controller:
var ref = firebase.database().ref('demodata/' + $localStorage.selectedoption);
$scope.demoscop = $firebaseArray(ref);
I am working on displaying collection that I got from DB in angular with firebase DB. I have those controller and service setup. in the html, I use search.users expecting it will hold all the data that I got from the DB but it won't show up. I can't figure out why. I tried few things like angular.copy or $broadcast with no luck. Can anyone help advise on this? Appreciated in advance.
.controller('SearchController', function ($scope, SearchService, logout, $location){
var search = this;
search.users = SearchService.users;
//$scope.$on('evtputUsers', function () {
// search.users = SearchService.users;
//});
})
//service for SearchService
.factory('SearchService', function ($http, $rootScope){
var userRef = new Firebase("app url");
var broadcastUsers = function () {
$rootScope.$broadcast('evtputUsers');
};
//get the user info
//insert the data to the db.
//retrieving the data
var dbUsers;
userRef.child('users').on('value', function(snapshot){
dbUsers = snapshot.val();
// angular.copy(snapshot.val(), dbUsers);
console.log('usersinDB:',dbUsers);
broadcastUsers();
}, function(err){
console.error('an error occured>>>', err);
});
return {
users: dbUsers
};
})
Rather than using $broadcast() and $on() you should use the AngularFire module.
AngularFire provides you with a set of bindings to synchronizing data in Angular.
angular.module('app', ['firebase']) // 1
.controller('SearchCtrl', SearchCtrl);
function SearchCtrl($scope, $firebaseArray) {
var userRef = new Firebase("app url")
$scope.users = $firebaseArray(userRef); // 2
console.log($scope.users.length); // 3
}
There are three important things to take note of:
You need to include AngularFire as firebase in the dependency array.
The $firebaseArray() function will automagically synchronize your user ref data into an array. When the array is updated remotely it will trigger the $digest() loop for you and keep the page refreshed.
This array is asynchronous. It won't log anything until data has populated it. So if you're logs don't show anything initially, this is because the data is still downloading over the network.
I'm currently learning AngularJS and similar stuff, and today I've encountered a problem (probably with async).
What I'm trying to do, is to use an Angular factory to get some data from Firebase and then use the data in a controller.
App.factory('Jobs', ['$firebaseObject', function($firebaseObject) {
var ref = new Firebase('https://myapp.firebaseio.com/Jobs');
return $firebaseObject(ref);
}]);
App.controller('JobsController', ['$scope', 'Jobs', function($scope, Jobs) {
Jobs.$bindTo($scope, 'allJobs');
console.log($scope.allJobs);
}]);
This is working pretty OK. When I put {{ allJobs | json }} in a template- it is updated after few seconds. The problem is that in the controller $scope.allJobs is returning undefined (probably because the response from Firebase arrived later than the code has been executed.
My question is, how to write it, so I can access $scope.allJobs directly in the controller?
You could do something like this:
App.factory('Jobs', ["$firebaseObject",
function($firebaseObject) {
// create a reference to the Firebase where we will store our data
return function(url){
var ref = new Firebase(url);
// this uses AngularFire to create the synchronized array
return $firebaseObject(ref);
};
}
]);
Then in your controller:
App.controller('JobsController', ['$scope', 'Jobs', function($scope, Jobs) {
$scope.allJobs = Jobs('https://myapp.firebaseio.com/Jobs');
$scope.allJobs.$loaded().then();
}]);
This is showing the $loaded method as opposed to $bindTo. As the other answers/comments mention, $bindTo may be the better way to go.
Referencing to this Firebase documentation: https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebaseobject-bindtoscope-varname
I can just do it very very simple:
App.controller('JobsController', ['$scope', 'Jobs', function($scope, Jobs) {
Jobs.$bindTo($scope, 'allJobs').then(function() {
// now I have access to $scope.allJobs when everything is downloaded from Firebase
});
}]);
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
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
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
Let say I want to retrieve user info from firebase,
and this user info will be displayed in several routes/controllers
Should I $rootScope the returned user info?
or
Call below code in each controller?
firebaseAuth.firebaseRef.child('/people/' + user.id).on('value', function(snapshot) {
$scope.user = snapshot.val();
})
UPDATE
I have a following service with a getUserInfo() function then what is the best way
to use it in several controllers?
calling firebaseAuth.getUserInfo().then() in each controller?
If the user data I have to use in several controller. Why don't I set it $rootScope?
So I don't need to call it again and again in different controllers.
myapp.service('firebaseAuth', ['$rootScope', 'angularFire', function($rootScope, angularFire) {
this.firebaseRef = new Firebase("https://test.firebaseio.com");
this.getUserInfo = function(id) {
var userRef = this.firebaseRef.child('/human/' + id);
var promise = angularFire(userRef, $rootScope, 'user', {});
return promise;
}
});
The point of AngularFire is to keep your javascript data model in sync with Firebase at all times. You don't want to create a new AngularFire promise every time you need to fetch data. You just initialize AngularFire once, and your local data will always be up to date.
myapp.service('firebaseAuth', ['angularFireCollection', function(angularFireCollection) {
this.firebaseRef = new Firebase("https://test.firebaseio.com");
this.initUserInfo = function(id) {
if (!this.userRef) {
this.userRef = this.firebaseRef.child('/human/' + id);
this.userInfo = angularFireCollection(this.userRef);
}
else {
// already initialized
}
}
}]);
Remember that all properties of your service (i.e. everything you assign using the this keyword) are accessible from controllers injected with this service. So you can do things like console.log(firebaseAuth.userInfo) or firebaseAuth.userRef.on('value', function(snap) { ... });
Also, you may eventually want to use the FirebaseAuthClient for your user authentication.
I would recommend creating a service to perform the authentication and store the user data. Then you can inject the service into any controller that needs access to the user.