I'm trying to get the value from service and then printing that value in console log which is giving me undefined in controller.
The value from service is being returned properly. But I'm not able to access vm.rrsData outside getRRSDetails function. vm.rrsData is comming as undefined outside the function.
Please suggest.
my controller :
(function () {
'use strict';
var angular = window.angular;
function RRSCtrl(
$translate,
RRSSvc
) {
var vm = this;
// Private
function getRRSDetails() {
RRSSvc.getRRSDetails()
.then(function (data) {
vm.rrsData = data;
});
}
getRRSDetails();
console.log('vm.rrsData'+ JSON.stringify(vm.rrsData)); // returning undefined here
}
angular
.module('quote')
.controller('RRSCtrl', [
'$translate',
'RRSSvc',
RRSCtrl
]);
}());
my service :
(function () {
'use strict';
var angular = window.angular;
function RRSSvc(
$http,
$q,
UserSvc,
UtilitiesSvc
) {
function rrsError(messageKey) {
UtilitiesSvc.showMessage(messageKey, 'error', 'generate-blank-demo-error');
}
function getRRSDetails(poID) {
return $http.get('quote/accounts/' + UserSvc.get('accountId') + '/pos/' + poID + '/rrs?serialNumber=')
.then(function (response) {
return response.data;
})
.catch(function (e) {
rrsError('quote.messages.GET_RRS_ERROR');
$q.reject(e);
});
}
return {
getRRSDetails: getRRSDetails
};
}
angular.module('quote')
.service('RRSSvc', [
'$http',
'$q',
'UserSvc',
'UtilitiesSvc',
RRSSvc
]);
}());
That's completely normal since you're making an asynchronous request.
consider these 2 lines:
getRRSDetails();
console.log('vm.rrsData'+ JSON.stringify(vm.rrsData)); // returning undefined here
console.log will run before the function above resolves. So, at that time vm.rrsData is undefined.
To see the value you must include console.log inside the function:
function getRRSDetails() {
RRSSvc.getRRSDetails()
.then(function (data) {
vm.rrsData = data;
console.log('vm.rrsData'+ JSON.stringify(vm.rrsData)); // has value from the http call
});
}
UPDATE
Another way to write the above and maybe more clear:
RRSSvc.getRRSDetails().then(onRSSDetails);
function onRSSDetails(response) {
// here you do whatever you want with data.
console.log(response);
}
Try to call your service in controller like this:
this.rrsData = null; //declare variavle to store service data
RRSSvc.getRRSDetails()
.then(function (data) {
this.rrsData = data;
}.bind(this)); // bind is the key to store the context
console.log('rrsData'+ JSON.stringify(this.rrsData));
Related
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.
(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.
In this case console logged all properties
app.controller("sgCtrl", function ($scope, $service)
{
var asd=service.getPerson();
console.log(asd);
}
But when im try to get some property its returned me undefined
...console.log(asd.person.Id)
My service
function service($http, $q) {
var service = {
person:[]
};
service.getPerson = function (personId) {
return $http.get('/P/GetP',
{params:{personId:personId}}).success(function (res) {
service.person = res.Person;
});
};
Issue is
1. $http.().success(function() {}) is asynchronous function. So service.person will be available only when control will come inside success callback handler.
2. You have not created service in the correct way.
You can try with below code:
Service code
function service($http, $q) {
this.getPerson = function (personId, successHandler) {
$http.get('/P/GetP',
{params:{personId:personId}}).success(function (res) {
successHandler(res.Person);
});
};
app.service('MyService', service);
Controller Code
app.controller("sgCtrl", function ($scope, MyService) {
function successHandler(person) {
console.log(person.IsActive);
}
MyService.getPerson('somePersonId', successHandler);
}
I believe it will resolve your issues.
Cheers!
for past 3 days , i have struggling in getting a value from nested service through controller,
I have a service 1 call and pass the service 1 call to service 2 and getting a response and pass to controller,In controller , i am getting undefined.
So when i pass a single response call , that means service1 call , getting a value in controller by using Ui route resolve.
What wrong here ?
This is my factory call.
app.factory('LogHomService', function (Service1, Service2)
{
var MyService = function (data)
{
Service1.log("user", encodeURIComponent("ad"))
.then(function(response) {
var FullUrl = response.strURL;
var objs = response.products; // getting the response here
Service2.pageLoad(objs)
.then(function(response) {
var homeScreen = response; // getting the response here
return homeScreen;
});
});
};
return {
MyService: MyService
}
});
Route call:
.state('home.prod', {
url: '/product',
views: {
'#': {
templateUrl: baseUrl + 'home/product',
controller: 'productController'
}
},
resolve: {
param2: function(LogHomService) {
return LogHomService.MyService();
}
}
})
Controller:
var productController = function ($scope, $rootScope, $state, $stateParams,param2)
{
console.log(param2); // getting undefined
}
productController.$inject = ['$scope', '$rootScope', '$state','$stateParams','param2');
Note:
When I return a single response getting a value in controller which means return a service 1 call getting response.
When i tried to return a service2 call getting undefined.
This is my factory call.
app.factory('LogHomService', function (Service1, Service2)
{
var MyService = function (data)
{
Service1.log("user", encodeURIComponent("ad"))
.then(function(response) {
var FullUrl = response.strURL;
var objs = response.products; // getting the response here
return objs;
});
};
return {
MyService: MyService
}
});
In response to your question in the comments, in order to access the data in the service in your controller, you could do something like this:
app.factory('LogHomService', function (Service1, Service2) {
var service = {}
service.myMethod = function (data) {
Service1.log("user", encodeURIComponent("ad"))
.then(function(response) {
var FullUrl = response.strURL;
//at this point, you will have access to LogHomService.objs
service.objs = response.products;
return service.objs;
});
};
return service
});
This line:
return LogHomService.MyService();
will always return null because MyService function returns nothing.
Here is a purposed fix:
var MyService = function (){
return Service1.log("user", encodeURIComponent("ad"))
.then(function(response) {
var FullUrl = response.strURL;
var objs = response.products;
return Service2.pageLoad(objs);
};
}
I've also cleared some unnecessary stuff.
Service2 object response from the controller,In controller getting Function call when i use return LogHomService.MyService; if i use return LogHomService.MyService(); shows undefined. i will attached the screenshot below.
But in Service response have values , Don't know why.
When I click the data , its shows factory code.
This question already has answers here:
Share data between AngularJS controllers
(11 answers)
Closed 2 years ago.
i have tow controller in angularjs. if one controller change data other controller display updated data. in fact first controller has a event that it occur second controller display it. for this propose i wrote a service. this service has tow function. here is my service code.
app.service('sharedData', function ($http) {
var data=[]
return {
setData: function () {
$http.get('/getData').success(function(response){
data = response;
})
},
getData: function(){
return data;
}
}
});
in first controller
app.controller("FirstController", function ($scope, $http,sharedData)
{
$scope.handleGesture = function ($event)
{
sharedData.setData();
};
});
in second controller:
app.controller("SecondController", function ($scope,sharedData) {
var data=[];
data = sharedData.getData();
}
);
in first controller setData work with out any problem but in second controller not work correctly. how to share data dynamically between tow controllers?
You are on the right track with trying to share data between controllers but you are missing some key points. The problem is that SecondController gets loaded when the app runs so it calls sharedData.getData() even though the call to setData in the firstController does not happen yet. Therefore, you will always get an empty array when you call sharedData.getData().To solve this, you must use promises which tells you when the service has data available to you. Modify your service like below:
app.service('sharedData', function ($http, $q) {
var data=[];
var deferred = $q.defer();
return {
setData: function () {
$http.get('/getData').success(function(response){
data = response;
deferred.resolve(response);
})
},
init: function(){
return deferred.promise;
},
data: data
}
})
And the secondController like this:
app.controller("SecondController", function ($scope,sharedData) {
var data=[];
sharedData.init().then(function() {
data = sharedData.data;
});
});
For more info on promises, https://docs.angularjs.org/api/ng/service/$q
You had multiple syntax problems, like service name is SharedData and you using it as SharedDataRange, the service is getting returned before the get function.
What I have done is corrected all the syntax errors and compiled into a plunkr for you to have a look. Just look at the console and I am getting the data array which was set earlier in the setter.
Javascript:
var app = angular.module('plunker', []);
app.controller("FirstController", function ($scope,sharedDateRange)
{
sharedDateRange.setData();
});
app.controller("SecondController", function ($scope,sharedDateRange) {
var data=[];
data = sharedDateRange.getData();
console.log(data);
});
app.service('sharedDateRange', function ($http) {
var data=[];
return {
setData: function () {
data = ['1','2','3'];
}
,
getData: function(){
return data;
}
}
});
Working Example
If you want to keep sharedDataRange as the variable name and service name as sharedData have a look at this example
javascript:
var app = angular.module('plunker', []);
app.controller("FirstController", ['$scope','sharedData', function ($scope,sharedDateRange)
{
sharedDateRange.setData();
}]);
app.controller("SecondController", ['$scope','sharedData', function ($scope,sharedDateRange) {
var data=[];
data = sharedDateRange.getData();
console.log(data);
}]);
app.service('sharedData', function ($http) {
var data=[];
return {
setData: function () {
data = ['1','2','3'];
}
,
getData: function(){
return data;
}
}
});
You can bind the data object on the service to your second controller.
app.service('sharedData', function ($http) {
var ret = {
data: [],
setData: function () {
$http.get('/getData').success(function(response){
data = response;
});
}
};
return ret;
});
app.controller("FirstController", function ($scope, sharedData) {
$scope.handleGesture = function () {
sharedData.setData();
};
});
app.controller("SecondController", function ($scope, sharedData) {
$scope.data = sharedData.data;
});
What you need is a singleton. The service sharedData needs to be a single instance preferably a static object having a static data member. That way you can share the data between different controllers. Here is the modified version
var app = angular.module('app', []);
app.factory('sharedData', function ($http) {
var sharedData = function()
{
this.data = [];
}
sharedData.setData = function()
{
//$http.get('/getData').success(function(response){
this.data = "dummy";
//})
}
sharedData.getData = function()
{
return this.data;
}
return sharedData;
})
.controller("FirstController", function ($scope, $http,sharedData)
{
sharedData.setData();
})
.controller("SecondController", function ($scope,sharedData) {
$scope.data=sharedData.getData();
});
I have removed the event for testing and removed the $http get for now. You can check out this link for a working demo:
http://jsfiddle.net/p8zzuju9/