Angular Service doesn't return value - angularjs

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.

Related

My Service is returning data to the controller but I cannot seem to access it like I would expect.

(function () {
angular.module("app").controller('DashboardController', ['$q', 'dashboardService', function ($scope, $q,dashboardService) {
var DashboardController = this;
dashboardService.loadFromServer(DashboardController );
console.log("DashboardController ", DashboardController);
}])
})();
angular.module("app").service('dashboardService', ['$http', '$q', function ($http, $q) {
return {
loadFromServer: function (controller) {
var getDashboardEntries = $http.get('http://someUrl');
var getEmailData = $http.get('http://someOtherUrl');
var getSidebarData = $http.get('http://yetAnotherUrl');
return $q.all([getDashboardEntries, getSidebarData, getEmailData])
.then(function (results) {
controller.dashboardData = results[0].data;
controller.chartData = results[1].data;
controller.emailData = results[2].data;
});
},
};
}]);
1.The service returns the three bits of data and this is the results when logged using:
console.log("DashboardController ", DashboardController);
When I try to drill down on the data in this manner it logs "undefined"
console.log("DashboardController "DashboardController.dashboardData);
console.log("DashboardController "DashboardController.chartData);
console.log("DashboardController "DashboardController.emailData);
Do you realize that console.log is executed right after invoking loadFromServer before the server has chance to respond and promise resolves? The actual order is:
loadFromServer
console.log
promise success method - where you actually have your data
Change your controller's code to this:
dashboardService.loadFromServer(DashboardController ).then(function() {
console.log("DashboardController ", DashboardController);
});
What would be even better is to construct some object from parts of responses and assign it in the controller itself - not the service. In current implementation if you wanted to have another controller then service would assign response parts to same fields. I'd propose sth like this:
return $q.all([getDashboardEntries, getSidebarData, getEmailData])
.then(function (results) {
var data = {
dashboardData = results[0].data;
chartData = results[1].data;
emailData = results[2].data;
};
return data;
});
and then in controller:
dashboardService.loadFromServer().then(function(data) {
DashboardController.dashboardData = data.dashboardData;
DashboardController.chartData = data.chartData;
DashboardController.emailData = data.emailData;
});
In this solution the controller decides what to do with data, not the other way around.

Send path from controller to a service which will return a promise back to controller

I have a service which get data from a file(path is given by the controller) and return a promise - then another service that create a object with properties using the returned data from the last service.
My problems are:
The getDataService runs before controller so it has no path from which to fetch data => nothing in return(an error)
Provider 'GetDataService' must return a value from $get factory method.
I need to keep this structure because I'll have more controllers with different paths to give
I'm also opened to other solutions but I need to make sure that datas are loaded before the template get populated. I've tried to call SetProperties service first with getData service into it - but still getData.js is executed first
getdata Service
angular.module('myApp').factory('GetDataService',['$http', function($http) {
var getData = function(path){
return $http.get(path).then(function(result) {
return result.data;
});
};
}]);
setProperties service
angular.module('myApp').service('PageProperties',['$http', function($http) {
this.setProps = function(page, data) {
some code here
var properties = {
isCenterActive : isActive_val,
//header elements
titleClass : page,
title : data.titles[page],
//footer elements
leftLink : leftLink_val,
leftFooterClass: leftLink_val,
leftTitle: data.titles[leftLink_val],
centerLink : centerLink_val,
centerFooterClass: data.titles[centerLink_val],
centerTitle : centerTitle_val,
rightLink : rightLink_val,
rightFooterClass: rightLink_val ,
rightTitle : data.titles[rightLink_val],
}
return properties;
}
}]);
controller
angular.module('myApp', [])
.controller('meniuController', ['$http', '$stateParams', '$scope', 'GetDataService', 'PageProperties',
function($http, $stateParams, $scope, GetDataService, PageProperties){
var page = "meniu";
$scope.language = $stateParams.lang;
var path = '_global/views/services/json/' + $stateParams.lang + '_data.json';
/*PageProperties.setProps(page, path).then(function(data){
//some code here
});*/
GetDataService.getData(path).then(function(data){
$scope.props = PageProperties.setProps(page, data);
}).catch(function(){
$scope.error = 'Unable to get data';
});
}])
Thanks in advance!!
The error says your GetDataService provider (defined as factory) doesn't return anything
angular.module('myApp').factory('GetDataService',['$http', function($http) {
var getData = function(path){
return $http.get(path).then(function(result) {
return result.data;
});
};
// you need to actually return something
return { getData: getData };
}]);
Then you can make your PageProperties use GetDataService
angular
.module('myApp')
.service('PageProperties',['GetDataService', function(GetDataService) {
this.getProperties = function(path) {
return GetDataService.getData(path).then(/*transform here*/)
}

Pass angular data between service to controller

i have my angular service and controller, i need to pass the data between service to controller to get value for voucher_code
Angular Service:
myApp.service('tradeData', function ($http) {
var service ={};
var voucher_code;
service.postTrade = function(trade){
console.log(trade)
console.log("TEST")
var promise = $http.post('tradein', trade);
promise.
then(function successCallback(response) {
angular.extend(trade, response.tradeData);
//console.log("======="+response.data)
voucher_code = JSON.stringify(response.data.voucher_code, null, 4); // (Optional) beautiful indented output.
console.log("test123",voucher_code);
return voucher_code;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
return promise;
};
return service;
})
Angular Controller:
myApp.controller('ModalInstanceCtrl', function($scope, $uibModalInstance, items, PersonalInfoService, tradeData) {
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel');
}
$scope.personal = PersonalInfoService;
$scope.printToCart = function(printSectionId) {
var innerContents = document.getElementById(printSectionId).innerHTML;
var popupWinindow = window.open('', '_blank', 'width=550,height=700,scrollbars=no,menubar=no,toolbar=no,location=no,status=no,titlebar=no');
popupWinindow.document.open();
popupWinindow.document.write('<html><head><link rel="stylesheet" type="text/css" href="css/print.css" media="screen, print" /></head><body onload="window.print()">' + innerContents + '</html>');
popupWinindow.document.close();
}
$scope.Product = tradeData;
console.log("sfsdff" , tradeData.voucher_code);
// console.log("santo", voucher_code);
// console.log("santo", service);
})
Any idea to pass the values of voucher_code from service to controller
Use this in your controller:
tradeData.postTrade().then(function(voucher_code) {
$scope.voucher_code = voucher_code;
)};
postTrade method returns the promise. So you can use the data it returns (get resolved with) by using the then method.

Angular : Share data returned from factory between controllers

I havea factory call HTTP end point to fetch user:
.factory('me', function($resource, VAS_API_URL, $q) {
return {
getUser: function() {
var deferred = $q.defer();
var url = VAS_API_URL + 'api/me';
$resource(url)
.get(function(user) {
deferred.resolve(user);
}, function(response) {
deferred.reject(response);
});
return deferred.promise;
}
};
})
I use this factory in many controllers and, i bind the data to the DOM successfully, but at times i want to use the data returned from the factory in my controller like to save the user name with a notification so i had to do the following:
.controller('createNotificationCtrl', function($scope, VAS_API_URL, me) {
var Burl = VAS_API_URL + 'api/notification';
$scope.profile = me.getUser();
$scope.profile.then(
function(user) {
$scope.owner = user;
$scope.item = {};
$scope.item.message = $scope.message;
$scope.item.owner = $scope.owner.displayName;
},
function(response) {
console.log(response);
}
);
})
I had to creat $scope.item = {}; in the factory call so i could get the displayName then send the object to save a notification but what if i want to save also another filed from another factory. How it could be done?
The factory should create the object and hold it as a state.
The controller's should use the reference from the factory and update it for everyone.
factory code sample:
this.stateObj = {};
....
....
this.getUser = function(){
var promise = $http.get(url);
promise.then(function(res){
// update stateObj
});
return promise;
}
ctrl code sample:
factory.getUser().then(function(res){
$scope.stateObj = factory.getStateObj();
});

Initiate a service and inject it to all controllers

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;
}
});

Resources