Adding Firebase Data to Angular Service? - angularjs

I am trying to inject my Firebase Object to a service so I can use different Angular Controllers to access copies of the Firebase Object.
In a previous working copy of my app. I only loaded Firebase into a controller:
Example Below:
ToDo.controller('todoController',["$scope","$firebaseArray", function($scope, $firebaseArray, ToDoData){ // injecting AngularFire & ToDoData Service
var myData = new Firebase("https:firebase url goes here"); //create Firebase obj
$scope.todos = $firebaseArray(myData); //Reading Database and adding to todos variable
$scope.historytodos = [{'title': "Old Task", 'done':true, 'timetag':new Date().toString()}];
$scope.addTodo = function(){
var datecreated = new Date().toString();
$scope.todos.$add({'title':$scope.newtodo,'done':false, 'timetag': datecreated}); //push to Array
$scope.newtodo = '';
};
Now I am trying to recreate the Firebase Dependency , but to work with a service. Here is what I have for my attempted Service.
It is erroring this
Uncaught ReferenceError: Todo is not defined
Example of my Erroneous service :
Todo.value('fbURL', "https:firebase") //Firebase URL value service
.service('fbRef',function(fbURL){ //Firebase Data Reference Service
return new Firebase(fbURL);
})
.service('fbArr',function(fbRef){ //Firebase Array service
$scope.todos = $firebaseArray(fbRef);
return $scope.todos;
});
Not sure what's causing the error & also not too sure how to create a service to hold my Firebase object.

First of all the error is self explanatory, Todo is not defined. You have to do something like:
var Todo = {fbRef: "https:firebase"};
And for the service i suggest you read up on services and factory's to see what applies best for your particular case and here is a simple example of how to do it in a service:
.service('fb', function(){
var connection = new Firebase(url);
var todos = $firebaseArray(connection);
this.url = function() { return connection;};
this.todos = function() { return todos;};
});

Related

Sending data from Angular 1.x Factory to Angular 1.x controller

I have a service defined which do the db related queries/updates. I have defined the controller which does the data parsing for the angular elements by getting the objects from the service. I would like to keep each scope different
How can I pass the data from service to controller using ngResource.
Sample Service:
app.factory("ioHomeService", ["$rootScope","$resource", function($rootScope,$resource) {
var svc = {};
var home = $resource('/home/getAll');
var dbData= home.get();
svc.getRooms = function() {
return dbData;
};
return svc;
}]);
Sample Controller:
app.controller("homeCtrl",["$scope","$mdDialog","ioHomeService",function($scope,$mdDialog,ioHome){
$scope.dbData = ioHome.getRooms();
//Here UI specific objects/data is derived from dbData
}]);
After the DB is queried and the results are avialble the dbData in service is reflecting the data from DB, but the Controller cannot get that data
It is important to realize that invoking a $resource object method
immediately returns an empty reference (object or array depending on
isArray). Once the data is returned from the server the existing
reference is populated with the actual data. This is a useful trick
since usually the resource is assigned to a model which is then
rendered by the view. Having an empty object results in no rendering,
once the data arrives from the server then the object is populated
with the data and the view automatically re-renders itself showing the
new data. This means that in most cases one never has to write a
callback function for the action methods.
From https://docs.angularjs.org/api/ngResource/service/$resource
Since the 'ioHome.getRooms();' is being called before the $resource has returned the data you are getting dbData as an empty reference
app.factory("ioHomeService", ["$rootScope","$resource", function($rootScope,$resource) {
var svc = {
dbData : {}
};
var home = $resource('/home/getAll');
var svc.dbData.rooms = home.get();
return svc;
}]);
Controller
app.controller("homeCtrl",["$scope","$mdDialog","ioHomeService",function($scope,$mdDialog,ioHome){
$scope.dbData = ioHome.dbData;
//You can access the rooms data using $scope.dbData.roooms
//Here UI specific objects/data is derived from dbData
}]);
You would have to return the service object , like so :
app.factory("ioHomeService", ["$rootScope","$resource", function($rootScope,$resource) {
var svc = {};
var home = $resource('/home/getAll');
var dbData= home.get();
svc.getRooms = function() {
return dbData;
};
return svc; //here
}]);
Currently the getRooms method is not visible to your controller.

angular display model on view after getting data from firebase

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.

firebase snapshot will not return value

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.

How to read response from angular resource $save() and also keeping original data

I am new to Angular. I am sure I am missing some basic stuff here.
I have one object which I post to the server to create it. The Server returns the object Id, which I need to read and update the object I have in the client.
The server will only return the object ID, however, at the client side, I have other data which I am not able to use when I perform a callback (I don't have access to the original data).
The Following jsfiddle code has been added as a reference:
//Get Angular Project module
var app = angular.module("app", ['ngResource']);
//create Project factory
app.factory('Project', function ($resource) {
return $resource('http://cmsanalyticsdev.pearson.com\\:8081/api/projects/:projectid',
{projectid:'#id'},
{update: {method:'PUT', isArray:false}}
);
});
//Controller for testing
app.controller('ApplicationController', function ($scope, Project) {
//Project object
var project = new Project({"name":"New Project Test","thumbnail":"","statusid":"521d5b730f3c31e0c3b1e764","projecttypeid":"521f585c092a5b550202e536","teamid":"521f585a092a5b550202e521","authors":[{"firstname":"Dilip","lastname":"Kumar"}],"projectspecificmetadata":{"isbn13":"345345","guid":"asfas"},"modifiedby":"521f585a092a5b550202e525"}
);
//Create new project
project.$save(project, function (projectResponse) {
project.projectId = projectResponse._id;
alert(project.name);
});
});
I think you want something like this:
//Controller for testing
app.controller('ApplicationController', function ($scope, Project) {
//Project object
var projectData = {"name":"New Project Test","thumbnail":"","statusid":"521d5b730f3c31e0c3b1e764","projecttypeid":"521f585c092a5b550202e536","teamid":"521f585a092a5b550202e521","authors":[{"firstname":"Dilip","lastname":"Kumar"}],"projectspecificmetadata":{"isbn13":"345345","guid":"asfas"},"modifiedby":"521f585a092a5b550202e525"};
var project = new Project(projectData);
//Create new project
project.$save(project, function (projectResponse) {
projectData.projectId = projectResponse.id;
console.log("ProjectData: %j", projectData);
});
});
Following is similar approach for $update.
//keep original data to pass into callback
var originalProjectObject = angular.copy(project);
//Call server to update the project data
project.$update({ projectid: project._id }, function (projectResponse)
{
originalProjectObject._id = projectResponse._id;
//update scope
scope.project = originalProjectObject;
},originalProjectObject);

Angularjs should I $rootScope data returned from firebase?

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.

Resources