$scope.object is undefined a $http promise - angularjs

I bit new to Angular, using controller, factory that keeps methods for the $http requests.
--------------In Service------------------------------
factory.getContract = function(guid) {
return $http
.get(Configuration.apiurl + '/contracts/' + guid, { headers: {"accesstoken": 'XXXXXXXXXX'}})
.then(function (response) {
return response;
});
};
--------------- In Controller ------------------
$scope.getContract = function (guid) {
ContractService.getContract(guid).then(
function (response) {
var data = response.data;
$scope.contract = {
contract_status: data.contract_status,
car: data.car,
properties: data.data
};
},
function (response) {
console.log('Error while loading the contract,', response);
}
);
};
if ($state.includes('contracts.edit')) {
$scope.getContract($stateParams.guid);
// In this controller, i check if requesting route is the Edit then get contract data. When i do this it works and fill the form with correct information. BUT AS I TRY TO ACCESS $scope.contract in console it says undefined
console.log($scope.contract);
}
What is wrong with my code?

$http.get is returning Promise, so just remove .then part from your factory if you want to execute callback inside controller:
factory.getContract = function(guid) {
return $http.get(Configuration.apiurl + '/contracts/' + guid,
{ headers:
{"accesstoken": 'XXXXXXXXXX'}
});
}

Related

using angular factory with $http

I need translate value factory. this factory receive translateData from server. and angular controller call convertValue function. but $http is async method so controller get undefined value. because http response not yet received.
I wonder that I can factory initialize complete(= download data from server) and create controller sequentially.
angular.module("app")
.factory("service", function ($http) {
var allDataMap = {};
$http({
method: 'GET',
url: '/data'
}).then(function (response) {
angular.forEach(response.data.datas, function (value) {
allDataMap[value.key] = value.value;
});
});
return {
convertValue: function (key) {
return key + '(' + allDataMap[key] + ')';
},
};
});
You're thinking of async call to be accomplish in sync way. That won't happen, you have to wait until the ajax call is done, you can easily make this happen using promise.
angular.module("app")
.factory("service", function ($http) {
var allDataMap = {};
// create a promise
var promise = $http({
method: 'GET',
url: '/data'
}).then(function (response) {
angular.forEach(response.data.datas, function (value) {
allDataMap[value.key] = value.value;
});
return allDataMap;
});
return {
convertValue: function (key) {
// wait until promise finish
return promise.then(function() {
return key + '(' + allDataMap[key] + ')';
});
},
};
});

How to call multiple GET requests using a resource factory in angular?

Here is my code for factory method using $resource
(function () {
"use strict";
angular.module("common.services")
.factory("lookupResource", ["$resource", "appsettings", lookupResource])
function lookupResource($resource, appsettings) {
return {
lookupUserRoles: $resource(appsettings.serverpath + "api/UserRoles", null,
{
'userRoles': { method: 'get' }
}),
lookupStaffTypes: $resource(appsettings.serverpath + "api/StaffTypes", null,
{
'staffTypes': { method: 'get' }
})
}
}
})();
I am trying to call the lookupStaffTypes using below code but it gives no data or error. What am I missing here?
lookupResource.lookupStaffTypes.staffTypes( function (data) {
var test = data;
},
function (response) {
vm.message = response.statusText + "\r\n"
if (response.data.exceptionMessage)
{ vm.message += response.data.exceptionMessage }
//validation errors
if (response.data.error) {
vm.message += response.data.error;
}
});
Where as I can call like this and it gives me data:
var staffTypes = $http.get(appsettings.serverpath + "api/StaffTypes").then(function (dataResponse) {
var qwe = dataResponse;
for (var i = 0; i < dataResponse.data.length; i++) {
$scope.staffTypeList.push(dataResponse.data[i]);
}
}, function (response) {
vm.message = response.statusText + "\r\n"
if (response.data.exceptionMessage)
{ vm.message += response.data.exceptionMessage }
//validation errors
if (response.data.error) {
vm.message += response.data.error;
}
});
I am new to angular and any help would be highly appreciated!
I recommend avoiding the ngResource module and just using the $http service directly. If a server implements a RESTful API, I recommend using Restangular.
That said, for ngResource:
If the server returns an array, it is important to define the action method with isArray: true:
app.factory("lookupResource", ["$resource", "appsettings", lookupResource])
function lookupResource($resource, appsettings) {
return {
lookupStaffTypes: $resource(appsettings.serverpath + "api/StaffTypes", null,
{
'staffTypes': { method: 'get',
isArray: true }
})
}
}
Invoke it with:
$scope.staffTypeList = lookupResource.lookupStaffTypes.staffTypes();
//OR
$scope.staffTypeList = lookupResource.lookupStaffTypes.query();
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.
If the service expects an object but receives an array, or vice versa, it will generate a $resource:badcfg error. If the service returns a boolean or a string, the action method will quietly return nothing.
Use the $promise propery of the received object (or array) to chain sequential operations:
$scope.staffTypeList.$promise.then(function(staffTypeList) {
console.log(staffTypeList);
//Do more stuff
});

synchronous and asynchronous calling in angularJS with promise and defer

I created following controller with 2 service calling with services. Second response comes before then first. i want to do like i need first response first and second response second. but i just stuck with async and sync please help me for solving.
Second call is depends on first call. For example if first call returns 10 record then i have to call second web service 10 time taking id from first response. so i use for loop but it is not proper.
Controller
var mycompaigndata = [];
asyncService.loadDataFromUrls($http.get(WSURL + 'api/first/',
{
headers:
{
"Authorization":'Bearer <my-token>'
}
}))
.then(function(data)
{
console.log(data);
});
asyncService.loadDataFromUrls($http.get(WSURL + 'api/second',
{
headers:
{
"Authorization":'Bearer <my-token>'
}
}))
.then(function(data)
{
console.log(data);
});
Service
app.service('asyncService', function($http, $q)
{
return {
loadDataFromUrls: function(url)
{
var deferred = $q.defer();
var urlCalls = [];
urlCalls.push(url);
$q.all(urlCalls)
.then(
function(results)
{
deferred.resolve(results)
},
function(errors)
{
deferred.reject(errors);
},
function(updates)
{
deferred.update(updates);
});
return deferred.promise;
}
};
});
To make sure the second calls are executed after the first one is finished, put the second call within then of the first call. To make multiple 'second' calls depending on the number of results of the first call, use $q.all.
asyncService.loadDataFromUrls('api/first/')
.then(function(firstData) {
//assuming firstData is an array of 'x' items, do a call for each of these items:
console.log('results of first call holds ' + firstData.length + ' items');
var promises = [];
for(var i = 0; i<firstData.length; i++){
var id = firstData[i].id;//you can use this to pass to the second call
promises.push(asyncService.loadDataFromUrls('api/second'));
}
return $q.all(promises);
})
.then(function(results) {
//'results' is an array of results, the nth item holds the result of the 'nth' call to loadDataFromUrls
for(var i = 0; i<results.length; i++){
console.log('result nr. ' + i + ' :' + results[i])
}
});
By using return $q.all(promises), you're avoiding the promise pyramid of doom, and keep a flat structure.
Your service code doesn't need to loop anymore. As a sidenote, you can shorten the code of the service and avoid using the 'explicit promise construction antipattern' (see here) like this:
app.service('asyncService', function($http, $q)
{
return {
loadDataFromUrls: function(url)
{
return $http.get(WSURL + url, {
headers: {
"Authorization": 'Bearer <my-token>'
}
}).then(function(response){ return response.data; });
}
};
});
Your asyncService seems completely unnecessary and unuseful.
It sounds like you just need to learn how to chain promises and use $q.all correctly:
function queryApi(subUrl) {
return $http.get(WSURL + subUrl, {
headers: {
"Authorization":'Bearer <my-token>'
}
}).then(function (result) { return result.data; });
}
queryApi('api/first/')
.then(function (data) {
return $q.all(data.map(function (entry) {
return queryApi('api/second/' + entry.id);
}));
})
.then(function (results) {
console.log(results);
});
put second request inside first request promise:
var mycompaigndata = [];
asyncService.loadDataFromUrls($http.get(WSURL + 'api/first/',
{
headers:
{
"Authorization":'Bearer <my-token>'
}
}))
.then(function(data)
{
asyncService.loadDataFromUrls($http.get(WSURL + 'api/second',
{
headers:
{
"Authorization":'Bearer <my-token>'
}
}))
.then(function(data)
{
console.log(data);
});
});
I think the best answer is to use loop since you need to iterate the response to get the id.
asyncService.loadDataFromUrls(WSURL + 'api/first/')
.then(function(data) {
//iterate to get the id
//call service again
asyncService.loadDataFromUrls(WSURL + 'api/first/')
.then(function(data) {
//code here
});
});
Service
app.service('asyncService', function($http, $q) {
return {
loadDataFromUrls: function(url) {
return $http.get(url, {
"Authorization":'Bearer <my-token>'
});
}
};
});

Angular js service returns function objects when called from a controller?

var newservices = angular.module('newservices', []);
newservices.service('newservice', function ($http) {
return{
newdata: function(parameter){
return $http.get('/devicedetails/'+parameter).success(function(data) {
console.log(data)
return data
});
},
}
});
The above service is included in one of my controllers
data=newService.newdata($scope.dummy)
console.log(data)
while trying to print data what i get is $http function object as shown below
Object {then: function, catch: function, finally: function, success: function, error: function}
why is this so??
What you see is not an error. It's a Promise.
You did an $http GET request, which is asynchronous. $http.getreturns a promise that will be resolved when the remote request is completed. In that moment, you'll get the final value.
See this example, where getShops would be your method newData
this.getShop = function (id, lang) {
var promise = $http.get(appRoot + 'model/shops_' + lang + '.json');
return promise;
};
In a controller you can use it like this:
Shops.getShop($routeParams.id).then(function (response) {
console.log("data is", response.data);
$scope.shop = response.data[$routeParams.id];
});
When the data is ready, assign it to a scope.
In your case:
var data;
newService.newdata($scope.dummy).then(function (response) {
data = response.data;
});
Your service is returnig a promise
You should use some what like this, not tested though it should work.
data = newService.newdata($scope.dummy).then(function (response) {
return response.data;
},
function (error) {
return error;
});
You are using it wrong.
This work in promises. so in you controller you need to consume the promisses.
newService.newData($scope.dummy)
.then(function (data){
$scope.data = data;
console.log(data);
});
Try this.

AngularJS: Creating a $http service

I'm a little new to Angular, and I'm trying to set up a very simple RPC implementation that uses angulars $http service (factory) to do the work. Here's what I have for the service so far:
'use strict';
angular.module('xxx')
.factory('rpcService', function ($http) {
return {
request: function(method, params, callback) {
var service = method.split('.');
params = params || {};
params.method = service[1];
return $http.post('/services/' + service[0] + '.sjs', params).then(function (response) {
return response.data;
});
}
}
});
Then when I want to use the service, I call it like the following:
rpcService.request('Users.facebookLogin', { token: response.authResponse.accessToken })
.then(function(response) {
debugger;
$rootScope.user = response.user;
console.log($rootScope.user);
$rootScope.loggedIn = true;
$rootScope.$apply();
});
The code never gets to the lines after debugger; In fact, the code never makes the $http request at all. For some reason it stops and doesn't continue with the callback...or promise...I'm a bit confused as to what the technical difference is. :)
That being said, I've tested the POST call with $.ajax and everything returns properly, so something is off with my Angular code.
And the code that actually fires the request and does work with $.ajax:
'use strict';
angular.module('xxx')
.factory('rpcService', function ($http) {
return {
request: function (method, params, callback) {
var service = method.split('.');
params = params || {};
params.method = service[1];
$.ajax('/services/' + service[0] + '.sjs', {
type: 'POST',
dataType: 'json',
data: params,
success: function(data, status, xhr) {
if (callback) {
callback(data);
}
}
});
}
}
});
I'm just unsure why the XHR request isn't being made.
The API call may get an error so the callback was never triggered. Try to add error() callback like this:
return $http("POST", '/services/' + service[0] + '.sjs', params)
.error(function (response) {
return 'blah';
}).then(function (response) {
return response.data;
});
You can try it on this demo. Your code actually looks good.
Demo on jsFiddle

Resources