Initiate a service and inject it to all controllers - angularjs

I'm using Facebook connect to login my clients.
I want to know if the user is logged in or not.
For that i use a service that checks the user's status.
My Service:
angular.module('angularFacebbokApp')
.service('myService', function myService($q, Facebook) {
return {
getFacebookStatus: function() {
var deferral = $q.defer();
deferral.resolve(Facebook.getLoginStatus(function(response) {
console.log(response);
status: response.status;
}));
return deferral.promise;
}
}
});
I use a promise to get the results and then i use the $q.when() to do additional stuff.
angular.module('angularFacebbokApp')
.controller('MainCtrl', function ($scope, $q, myService) {
console.log(myService);
$q.when(myService.getFacebookStatus())
.then(function(results) {
$scope.test = results.status;
});
});
My problem is that i need to use the $q.when in every controller.
Is there a way to get around it? So i can just inject the status to the controller?
I understand i can use the resolve if i use routes, but i don't find it the best solution.

There is no need to use $q.defer() and $q.when() at all, since the Facebook.getLoginStatus() already return a promise.
Your service could be simpified like this:
.service('myService', function myService(Facebook) {
return {
getFacebookStatus: function() {
return Facebook.getLoginStatus();
}
}
});
And in your controller:
.controller('MainCtrl', function ($scope, myService) {
myService.getFacebookStatus().then(function(results) {
$scope.test = results.status;
});
});
Hope this helps.

As services in angularjs are singleton you can create new var status to cache facebook response. After that before you make new call to Facebook from your controller you can check if user is logged in or not checking myService.status
SERVICE
angular.module('angularFacebbokApp')
.service('myService', function myService($q, Facebook) {
var _status = {};
function _getFacebookStatus() {
var deferral = $q.defer();
deferral.resolve(Facebook.getLoginStatus(function(response) {
console.log(response);
_status = response.status;
}));
return deferral.promise;
}
return {
status: _status,
getFacebookStatus: _getFacebookStatus
}
});
CONTROLLER
angular.module('angularFacebbokApp')
.controller('MainCtrl', function ($scope, $q, myService) {
console.log(myService);
//not sure how do exactly check if user is logged
if (!myService.status.islogged )
{
$q.when(myService.getFacebookStatus())
.then(function(results) {
$scope.test = results.status;
});
}
//user is logged in
else
{
$scope.test = myService.status;
}
});

Related

Unable to inject one factory into another factory in angularjs 1 and send token to angularjs application

I have an application which is a php application. I want this application to reside in my primary domain (primarydomain.com purposely for Single-Sign-On(to manage account details). Every user login here and upon successful login, redirect to one of my app hosted on a first.primarydomain.com. Upon redirection, authorize the user by checking if the user really logged in.
Now I have hosted an angularjs application in first.primarydomain.com
In my angularjs project, I have created a factory file which has 2 factory
1. Data
2. Auth.
The Data is for database operation while the Auth is meant for authorization check and logging out users.
Below is my code.
App.js
/* Init global settings and run the app */
app.run(["$rootScope", "settings", "$state", "$location", "Auth", function($rootScope, settings, $state, $location, Auth) {
$rootScope.$state = $state; // state to be accessed from view
$rootScope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams) {
if (!$rootScope.authenticated || $rootScope.authenticated==false){
var user;
Auth.isLoggedIn()
user=JSON.parse(localStorage.getItem('currentUser'));
console.log(user)
if(!user){
window.location="http://primarydomain.com/login"
}else{
//this.authenticated=true;
//this.loggedUser=user;
$rootScope.authenticated = true;
$rootScope.loggedUser =user;
}
}
//console.log($state)
});
}]);
//Factory.js
//Data. factory
//do some database query
app.factory("Data", ['$http', '$location', function ($http, $q, $location) {
var serviceBase = 'server/f3';
var obj = {};
obj.get = function (q) {
//alert(q)
return $http.get(serviceBase + q).then(function (results) {
return results.data;
});
};
obj.gets = function(q,config){
return $http.get(serviceBase + q,config);
}
obj.post = function (q, object) {
return $http.post(serviceBase + q, object).then(function (results) {
return results.data;
});
};
obj.posts = function (q, object) {
return $http.post(serviceBase + q, object, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined,'Process-Data': false}
}
)
.then(function (results) {
return results.data;
})
};
obj.put = function (q, object) {
return $http.put(serviceBase + q, object).then(function (results) {
return results.data;
});
};
obj.delete = function (q) {
return $http.delete(serviceBase + q).then(function (results) {
return results.data;
});
};
return obj;
}]);
app.factory('Auth', ['$http', '$location','Data', function ($http,$location,Data){
var obj = {};
obj.isLoggedIn = function(){
var user=JSON.parse(localStorage.getItem('currentUser'));
if(!user){
Data.get('/webpass/1').then(function(datas){
if(datas.type==1){
//alert('response good')
//console.log(datas.response)
localStorage.setItem('currentUser', JSON.stringify(datas.response));
return datas.response;
}else{
return false;
}
});
}else{
//alert('deji')
return (user)?user:false;
}
};
obj.Logout= function(){
//console.log('deji')
Data.get('/logout').then(function(datas){
//console.log(datas)
if(datas.type==1){
localStorage.removeItem('currentUser');
return true;
}else{
return false;
}
});
};
return obj;
}]);
<!-- end snippet -->
//Logout controllers
app.controller('LogoutController', function($rootScope, $scope, $location, Auth) {
Auth.Logout();
var user=JSON.parse(sessionStorage.getItem('currentUser'));
if(!user){
$rootScope.authenticated=false;
$rootScope.loggedUser=null;
window.location='http://primarydomain/login';
}else{
//alert('Unable to log user out')
$location.path('/dashboard');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
In the factory, none of the factory function can call the injected factory. It actually doesn't give any error but while tracking the execution flow, I realized that it doesn't even execute that part of the factory.
Another problem is that after successful login on the primarydomain.com, I want to send a token alongside the first.primarydomain.com which contains some user information and the access details. Please, how do I do this with angularjs 1.
Please help.
Check whether you have any injection issues by changing
app.factory("Data", ['$http', '$location', function ($http, $q, $location) {
to
app.factory("Data", ['$http', '$q', '$location', function ($http, $q, $location) {
You are not returning the values from isLoggedIn function. A simpler example of how it needs to work:
return $http.get(url).then((res) => {
return res.data;
}
Notice both return used, since we also need to return a Promise as well as its value.
You have failed to return the Promise:
Data.get('/webpass/1').then(function(datas){
/* Some code here */
return datas.response;
});
Instead it should be:
return Data.get('/webpass/1').then(function(datas){
/* Some code here */
return datas.response;
});

Angular Service doesn't return value

Im using angularjs in MVC.
Here My Controller.js:
//Get User By ID
$scope.GetUserById = function (UID) {
var Get = UserService.GetUserById(UID);
Get.then(function (response) {
$scope.User = response.data;
alert($scope.User.Address);
});
};
services.js:
//Get By ID
this.GetUserById = function (UID) {
debugger;
return $http.get("../api/UsersData/GetUserById?UID=" + UID);
};
When I'm using the debugger, the alert message is displayed. If I'm not debugging then it doesn't return a value.
What is the issue in my code?
How to display the value to html page?
You should get it working with few adjustments.
Service.js:
angular.module('myApp').factory('MyService', MyService);
//Avoid Minification Problems
MyService.$inject = [ '$http' ];
function MyService( $http ){
function GetUserById(UID){
return $http.get('../api/UsersData/GetUserById?UID=' + UID)
.then( function (response) {
if(response){
return response;
}
});
}
//Expose Method to External Calls
return {
GetUserById : GetUserById
}
}
Controller.js:
angular.module('myApp').controller('MyController', MyController);
MyController.$inject = [ '$scope', 'MyService' ];
function MyController( $scope, MyService ){
$scope.GetUserById = function(UID){
MyService.GetUserById(UID).then( function(response){
$scope.User = response.data;
alert($scope.User.Address);
});
}
}
Make sure what response is actually returning with a $log or using console.log in order to properly alert the address. Do this check also in the service, for instance you should check if response.address exists.
You can also use a Service instead of a Factory.

Angularjs data binding between controller and service

I'm not able to get the data binding between controller and service working.
I have a controller and a factory which makes an HTTP call. I would like to be able to call the factory method from other services and see the controller attributes get updated. I tried different options but none of them seem to be working. Any ideas would be greatly appreciated.
Please see the code here:
http://plnkr.co/edit/d3c16z?p=preview
Here is the javascript code.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
app.controller('EventDetailCtrl', ['$http', 'EventDetailSvc', '$scope',
function ($http, EventDetailSvc, $scope) {
this.event = EventDetailSvc.event;
EventDetailSvc.getEvent();
console.log(self.event);
$scope.$watch(angular.bind(this, function () {
console.log('under watch');
console.log(this.event);
return this.event;
}), function (newVal, oldVal) {
console.log('under watch2');
console.log(newVal);
this.event = newVal;
});
}])
.factory('EventDetailSvc', ['$http', function ($http) {
var event = {};
var factory = {};
factory.getEvent = function() {
$http.get('http://ip.jsontest.com')
.then(function (response) {
this.event = response.data;
console.log('http successful');
console.log(this.event);
return this.event;
}, function (errResponse) {
console.error("error while retrieving event");
})
};
factory.event = event;
return factory;
}]);
It seems to me that you have nested the event object inside of a factory object. You should be returning event directly instead wrapping it with factory. As it stands now you would need to call EventDetailSvc.factory.event to access your object.

Confusion about data usage in Controllers

How can I use the fetched data in customersController in AnotherCustomersController
function customersController($scope, $http) {
$http.get("http://www.w3schools.com//website/Customers_JSON.php")
.success(function(response) {$scope.names = response;});
}
function AnotherCustomersController($scope){
//What should I do here??
}
Full Details Here
You can share data between controllers using $rootscope but I don't think this is a best practice so my solution contain usage of angular service -> plnkr
app.factory('CustomerService', function ($http) {
return {
fetchData: function () {
return $http.get('http://www.w3schools.com//website/Customers_JSON.php')
}
}
});
app.controller('customersController', function ($scope, CustomerService) {
CustomerService.fetchData().success(function (response) {
$scope.names = response;
});
});
app.controller('AnotherCustomersController', function ($scope, CustomerService) {
CustomerService.fetchData().success(function (response) {
$scope.names = response;
});
});
Additionally i have refactor your code so only one app is used on page. If you want to use more than one you have to bootstrap them manually -> Read More

Load views after services in angularjs

In my angular app I have a view, a controller and a service.
The service load resources ex:service load persons and initialize value with the result.
I want to load my view after my service finish his function to load his resources.
var myApp = angular.module('myApp',[]);
myApp.controller('PersonsCtrl', ($scope, Persons) {
$scope.persons = Persons.data;
});
myApp.factory('Persons', {
data: [[function that load resources => take time]]
});
So I want to load my controller when my service finish his initialization.
Some ideas?
Assuming you have a route provider, here's a basic example. When the promise is resolved, "personData" will be injected into your controller. There's not much info about what your service does, so I had to give something very generic.
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/persons', {
controller: 'PersonsCtrl',
templateUrl: 'persons.html',
resolve: {
personData: ['Persons', function(Persons) {
return Persons.getData();
}]
}
});
}]);
myApp.controller('PersonsCtrl', ($scope, personData) {
$scope.persons = personData;
});
myApp.factory('Persons', {
getData: function() {//function that returns a promise (like from $http or $q)};
});
Maybe try using promises, example below
var myApp = angular.module('myApp',[]);
myApp.controller('PersonsCtrl', ($scope, Persons) {
$scope.persons = Persons.getData().then(function(response){
//do whatever you want with response
});
});
myApp.factory('Persons', function ($http, $q) {
return {
getData: function () {
var def = $q.defer();
$http.get('url').
success(function (response) {
def.resolve(response);
})
return def.promise();
}
}
});

Resources