how to access the response inside controller from a nested $http which is inside a factory. here we are having two service calls.one inside another.I need the response of the second service call in my controller. I am able to access the factory from controller and also the response inside the factory but when comes to controller success function, it's showing success function is not defined.
factory code : here i am calling nested $http service calls
bosAppModule.factory("ServiceCalls",function($http){
var ServiceCalls={};
var createFilterString = function(crudObject, callback) {
var filterString = "";
var keyValuePairs = [];
// iterate over the property
for(var property in crudObject) {
if(!(crudObject[property] instanceof Object)) {// if it is primitive type
// check the value is not null or undefined
if(crudObject[property] && crudObject[property] != "")
// added the key value string
keyValuePairs.push(property + "~;~" + crudObject[property]);
}
}
// add first key value pair
if(keyValuePairs[0])
filterString += keyValuePairs[0];
// iterate over the key value strings
for(var i = 1; i < keyValuePairs.length; i++) {
filterString += "~$~" + keyValuePairs[i];
}
try {
if(callback) callback(filterString);
} catch(e) {
console.log("Exception inside $dataTransactor->createFilterString" + e.message);
}
};
// var headers = {Authorization: COOKIES.readCookie("Authorization"),requestmode:"ACK_URL"};
// headers.isRender = file.isRender;
// if(file.inputDataHeaders)
// headers.inputData = file.inputDataHeaders;
ServiceCalls.getData = function(filterObject, file){
createFilterString(filterObject, function(filterString){
var headers = {Authorization: COOKIES.readCookie("Authorization"),requestmode:"ACK_URL"};
headers.isRender = file.isRender;
if(file.inputDataHeaders)
headers.inputData = file.inputDataHeaders;
$http({
method: 'GET',
url: file.fileUrl + "/" + $securityComponent.cryptograghicFunctions.encryptor(filterString),
headers: headers
})
.then(function(requestHandlerResponce) {
console.log(requestHandlerResponce);
$http({
method: 'GET',
url: requestHandlerResponce.data.links[1].href,
headers: headers
}).then(function(responceHandlerResponce) {
console.log("##### : "+JSON.stringify(responceHandlerResponce.data));
return responceHandlerResponce;
});
})
});
};
return ServiceCalls
});
controller code : here I need the response
bosAppModule
.controller(
"custom-entity-design-ctrl",
function($scope, $document, $http, $localStorage, navigateEntityUrl, entityFormation,layoutDesignFactory, ServiceCalls) {
var layoutDesignFac=new layoutDesignFactory();
var entityJson='{"entityInfo":{"entity":"","tenantId":"2b69af63-e2dc-43e5-9f0e-9fde52032d4c","timeStamp":"Tue Jun 16 2015 19:05:09 GMT+0530 (India Standard Time)"},"collections":{"Entity":{"meta":{"parentReference":"***","pkName":"***","fkName":"***"},"rowSet":[],"rowFilter":[]}}}';
var crudObject = {};
var file = {
fileUrl: $config.UIMetaData,
inputDataHeaders: entityJson
};
ServiceCalls.getData(crudObject,file).success(function(response){console.log(response)});
});
Your services should be returning the promises (the $http call in your case) to the controller:
return $http({ // return this promise
method: 'GET',
url: file.fileUrl + "/" + $securityComponent.cryptograghicFunctions.encryptor(filterString),
headers: headers
}).then(function(requestHandlerResponce) {
console.log(requestHandlerResponce);
return $http({ // return this promise as well
method: 'GET',
url: requestHandlerResponce.data.links[1].href,
headers: headers
}).then(function(responceHandlerResponce) {
console.log("##### : "+JSON.stringify(responceHandlerResponce.data));
return responceHandlerResponce;
});
And just to be consistent try to use the standard .then method rather than .success or .error in your controller:
ServiceCalls.getData(crudObject,file).then(function(response) {
console.log(response)
});
Last somewhat irrelevant note, I think 'response' is misspelled in your service ;)
Related
I don't quite understand the convention of the following line from the code below
request.transformRequest = internal.transformRequest;
Is this actually calling the internal.transformRequest function, or just setting the function equal to a method of the same name in the request object? I think it's calling the function because transformRequest is never called anywhere else in the code, but how are the parameters of data and getHeaders passed in that case?
internal.transformResourceUrl = function (url) {
if (url.substr(-1) === '/')
url = url.substr(0, url.length - 1);
return url + '.json';
};
internal.transformRequest = function (data, getHeaders) {
// If this is not an object, defer to native stringification.
if (!angular.isObject(data)) {
return (data === null) ? '' : data.toString();
}
var buffer = [];
// Serialize each key in the object.
for (var name in data) {
if (!data.hasOwnProperty(name)) continue;
var value = data[name];
buffer.push(
encodeURIComponent(name) +
'=' +
encodeURIComponent((value === null) ? '' : value )
);
}
// Serialize the buffer and clean it up for transportation.
var source = buffer
.join('&')
.replace(/%20/g, '+')
;
return source;
};
internal.generateRequest = function (method, resource, data, account) {
method = method.toUpperCase();
if (!angular.isString(account) || account.length < 1)
account = '_default';
resource = 'Accounts/' +
accounts[account] + '/' +
internal.transformResourceUrl(resource);
var request = {
method: method,
url: apiEndpoint + resource,
headers: {
'Authorization': 'Basic ' + credentialsB64
}
};
if (method === 'POST' || method === 'PUT') {
if (data) request.data = data;
request.transformRequest = internal.transformRequest;
request.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8';
} else if (data) {
request.params = data;
}
return $http(request);
};
"Is this actually calling the internal.transformRequest function, or just setting the function equal to a method"
"I think it's calling the function because transformRequest is never called anywhere else in the code"
How internal.transformRequest method get's called
line 7 : transformRequest :method(function) is added to internal :object
internal.transformRequest = function (data, getHeaders) {
line 54 : transformRequest propery of request :object is assigned to above method
request.transformRequest = internal.transformRequest;
line 59: $http() :function is called with request :object who now has
transformRequest :method which points to internal.transformRequest
return $http(request);
In my console the error is coming "getIdData is not defined" what is wrong with my code. Here deal is my service and getIdData is my function in service.
$scope.editUserDetail = function editUserDetail(){
$scope.showEditView = !$scope.showEditView;
$scope.showSubmitView = !$scope.showSubmitView;
console.log(deal);
deal.getIdData().then(function successCb(data){
$scope.editIdOptionsData=data;
});
};
Please check working example here: Demo
You are forget to return service object from service.
i.e
Write following code in your service,
return service;
i.e
angular.module('account').service('deal', function deal($http, accountConfiguration, $q, $log, httpHelper) {
var service = {};
var baseUrl = account.app.url;
service.getIdData = function(data, accountId, decisionMakerDetail) {
var def = $q.defer();
var url = baseUrl + '/api/accountsusers/' + accountId + '?role=' + decisionMakerDetail;
httpHelper._$http({
method: 'post',
url: url,
data: data,
def: def
}, function(resp) {
def.resolve(resp.msg);
});
return def.promise;
};
return service;
});
Or as you are using service you can write it using this
angular.module('account').service('deal', function deal($http, accountConfiguration, $q, $log, httpHelper) {
var baseUrl = account.app.url;
this.getIdData = function(data, accountId, decisionMakerDetail) {
var def = $q.defer();
var url = baseUrl + '/api/accountsusers/' + accountId + '?role=' + decisionMakerDetail;
httpHelper._$http({
method: 'post',
url: url,
data: data,
def: def
}, function(resp) {
def.resolve(resp.msg);
});
return def.promise;
};
});
For more information please check - Services
Please clean your browser and inspect source.Look deal.getIdData() is loaded or not.May be it is not loaded.Please load properly.
The object you are sending as a parameter doesn't have the getIdData() function defined.
Change your log to:
console.log(deal.getIdData);
and then check whether it returns the function code/definition.
Here is a link with an example of how implement a factory and service.
Angular factory and service
You are not returning the object holding the service reference from you your service registration function. Change your code as below for it to work.
angular.module('account')
.service('deal', function deal($http, accountConfiguration, $q, $log, httpHelper) {
var service = {};
var baseUrl = account.app.url;
service.getIdData = function(data,accountId,decisionMakerDetail){
var def = $q.defer();
var url = baseUrl + '/api/accountsusers/' + accountId + '?role=' + decisionMakerDetail;
httpHelper._$http({
method: 'post', url: url, data: data, def: def
}, function (resp) {
def.resolve(resp.msg);
});
return def.promise;
};
return service;
});
S8nce you were not returning anything from the service, even though deal service gets registered, its value is undefined and when you try to access deal.getIddata() you get the aforementioned error
I am stuck on some problems , actually I was in problem solved , the problem was header which is not enableing to get response (like CORS issue) ,overcome by using header and transformRequest as shown in below code. After that I got webservice data but in one controller used $rootscope which render some of id of data of second method (API) to use in another controller to put on third one api to get data and I am getting this for only a minute then it will throw error : Cannot read property 'companies data' of null which is field in third api. when I used $rootScope.Test.companies[0].companyname which is store data, and unique for all api like primary key.
var request = $http({
method: "post",
url: "http://app.xyz/xyzapp/public/user/login",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
str.push(encodeURIComponent('email_id') + "=" + encodeURIComponent('demo#xyz.com'));
str.push(encodeURIComponent('password') + "=" + encodeURIComponent('demo#xyz'));
return str.join("&");
},
});
request.success(function( response ) {
console.log("Hiiiii::::"+JSON.stringify(response,status));
if (response.status=="success"){
$rootScope.Test1=response.user_id;
var request1 = $http({
method: "post",
url: "http://app.xyz/xyzapp/public/company/getUserCompanyList",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
str.push(encodeURIComponent('user_id') + "=" + encodeURIComponent(response.user_id ));
// str.push(encodeURIComponent('password') + "=" + encodeURIComponent('demo#123'));
return str.join("&");
}
});
// getCompany
request1.success(function( response ) {
console.log("Hiiiii::::"+JSON.stringify(response,status)+" "+response.companies.length+":Length");
if (response.status=="success"){
// alert(1);
$state.go('tabdash');
$rootScope.Test = response;
}
});
So please tell me how to use one controller data to another where I am using another api which will get $rootscope date of parent.
Please let me know if anybody know about that or anything
Thanks
Yes you can use variables of one controller inside another controller using two methods
Create Service to communicate between them.
Use $rootScope.$broadcast
sample code
angular.module('myservice', []).service('msgBus', function() {
this.serviceValue= {};
}]);
});
and use it in controller like this:
controller 1
angular.module('myservice', []).controller('ctrl1',function($scope, msgBus) {
$scope.sendmsg = function() {
msgBus.serviceValue='Hello';
}
});
controller 2
angular.module('myservice', []).controller('ctrl2',function($scope, msgBus) {
$scope.checkValue(){
alert( msgBus.serviceValue);
}
});
I would like to log if there is no data in some returned Javascript object. Since http calls are asynchronous, my implementation doesn't work. I'm checking if the object is empty and if it is, I would like to log it's id. How could I get the right scenarioId to my else statement?
for (var i in $scope.scenarioData){
var scenarioId = $scope.scenarioData[i].id;
dataService.getResultsByScenarioId(scenarioId).then(function(response){
if (Object.keys(response.data).length != 0){
//This is not interesting in this context
}
else{
//I would like to log the called scenarioId here
$log.info("No data in scenarioId: " + scenarioId);
}
});
}
This is the used service
ptraApp.service('dataService', function($http) {
this.getResultsByScenarioId = function(id) {
return $http({
method: 'GET',
url: '/ptra/resultArchive/' + id,
});
}
});
Extract the function that call to servive to external function
for example:
for (var i in $scope.scenarioData){
var scenarioId = $scope.scenarioData[i].id;
getResult(scenarioId)
}
function getResult(scenarioId){
dataService.getResultsByScenarioId(scenarioId).then(function(response){
if (Object.keys(response.data).length != 0){
//This is not interesting in this context
}
else{
//I would like to log the called scenarioId here
$log.info("No data in scenarioId: " + scenarioId);
}
});
}
Should be something like that snippet:
ptraApp.service('dataService', function($http) {
this.getResultsByScenarioId = function(id) {
return $http({ method: 'GET', url: '/ptra/resultArchive/' + id}).
success(function (data, status, headers, config) {
console.log(data);
}).
error(function (data, status, headers, config) {
// ...
);
}});
here is a piece of code I am struggling with - I have a controller (zmApp.MonitorCtrl) that is calling a factory (ZMFactory) with an HTTP request.
The problem I am facing is this:
a) When the controller calls ZMFactory.getMonitors() it returns undef and I get an error
ERROR: Error: undefined is not an object (evaluating 'ZMFactory.getMonitors().then')
b) After this error comes up, the http request in the factory is processed
I am a little confused. Can you please check if the factory has been set up correctly to return a promise?
var app = angular.module('zmApp.controllers');
app.controller('zmApp.MonitorCtrl', function($ionicPlatform, $scope,$http,ZMFactory)
{
$scope.monitors=[];
console.log("***CALLING FACTORY");
ZMFactory.getMonitors().then(function(data)
{
$scope.monitors = data;
console.log ("I GOT " +$scope.monitors);
});
});
app.factory('ZMFactory',['$http', '$rootScope',function($http,$rootScope)
{
//var factory = {};
var monitors =[];
return {
getMonitors: function()
{
console.log("***MAKING REQUEST");
$http({
url:'http://myurl.com:9999/zm/index.php?skin=xml',
method:'post',
headers: {'Content-Type': 'application/x-www-form-urlencoded',
'Accept': '*/*',
},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
var foo= str.join("&");
console.log ("****RETURNING "+foo);
return foo;
},
transformResponse: function(data)
{
var x2js = new X2JS();
var json = x2js.xml_str2json(data);
console.log ("***Transmogrifying XML to JSON");
return json;
},
data: {username:'xxx',
password:'xxxx',
action:'login',
view:'console'}
}) //http
.success (function(data)
{
console.log("****YAY"+JSON.stringify(data));
var subobj =data.ZM_XML.MONITOR_LIST.MONITOR;
var len = subobj.length;
for (var i =0; i< len; i++)
{
console.log ("HERE " + subobj[i].NAME);
monitors.push(subobj[i]);
}
// $rootScope.$broadcast ('handleZoneMinderMonitorsUpdate',monitors);
return monitors;
}) //success
.error(function(data, status, headers, config)
{
console.log("***OOPS "+status + " H: "+data);
return monitors;
});
} //getMonitors
};//return
console.log ("**** NEVER *****");
}]);
The key to the answer is in the wording of your own question:
Can you please check if the factory has been set up correctly to return a promise
You need to return it. Right now your getMonitors function (if I remove all the code irrelevant to the question) is as follows:
getMonitors: function(){
$http({})
.success(function(data){
// convert data to monitors
return monitors;
});
}
This is a function call that doesn't return anything, or rather, returns undefined. There is no "magic" with promises - it's just as any other object - you need to return it to the caller.
So, two things you need to do:
1) Change from .success to .then. .then generates a new chained promise that delivers, when returned, the monitors to the consumer (that you are returning in the .then handler). On the other hand, .success returns the original promise (generated by $http) and data returning from .success is lost.
2) Actually return the $http call (or, rather, $http().then() call)
Here's conceptually how this would look like:
app.factory('ZMService', function ZMServiceFactory($http){
return {
// getMonitors function of the ZMService service
getMonitors: function(){
return $http({})
.then(function(response){
var data = response.data;
// convert data to monitors
return monitors;
});
}
};
});
(also, noticed how I renamed your service from ZMFactory to ZMService. A "factory" in the name is a misnomer. The factory is the function that generates the instance - hence "the factory" - but the instance itself is an object, which is called a "service" in Angular)
try with this,here i am returning the promise as is
var app = angular.module('zmApp.controllers');
app.controller('zmApp.MonitorCtrl', function($ionicPlatform, $scope,$http,ZMFactory)
{
$scope.monitors=[];
console.log("***CALLING FACTORY");
ZMFactory.getMonitors().then(function(data)
{
$scope.monitors = data;
console.log ("I GOT " +$scope.monitors);
});
});
app.factory('ZMFactory',['$http', '$rootScope',function($http,$rootScope)
{
//var factory = {};
var monitors =[];
return {
getMonitors: function()
{
return $http({
url:'http://myurl.com:9999/zm/index.php?skin=xml',
method:'post',
headers: {'Content-Type': 'application/x-www-form-urlencoded',
'Accept': '*/*',
},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
var foo= str.join("&");
console.log ("****RETURNING "+foo);
return foo;
},
transformResponse: function(data)
{
var x2js = new X2JS();
var json = x2js.xml_str2json(data);
console.log ("***Transmogrifying XML to JSON");
return json;
},
data: {username:'xxx',
password:'xxxx',
action:'login',
view:'console'}
}) //http
.then(function(data)
{
console.log("****YAY"+JSON.stringify(data));
var subobj =data.ZM_XML.MONITOR_LIST.MONITOR;
var len = subobj.length;
for (var i =0; i< len; i++)
{
console.log ("HERE " + subobj[i].NAME);
monitors.push(subobj[i]);
}
// $rootScope.$broadcast ('handleZoneMinderMonitorsUpdate',monitors);
return monitors;
},function(error)
{
return error;
});
}
};
}]);