nested angular http.get calls - javascript

I have a simple angular $http.get, which returns a json object, but I want the id from the json to do another $http.get. I can do this by nesting another $http.get with the first one, but this seems rather stupid. What is the best way to assign the id of the response, data.id, to a variable? I'm having some issues with variable scope; trying to simply assign the value to a variable.
$http.get('/api/v1/foo/userinfo?thunk='+thunk+'&bar='+bar).success(function(data) {
$scope.id = data.id
}).then(function(data){
$scope.id = data.data.id
});

Why don't you watch your variable, in this case $scope.id like this:
$scope.$watch('id', function() {
// Http request goes here
$http.get(...)
});
When you assigned any value to $scope.id your "watch function" will be triggered.

Can use callbacks to make it cleaner. Wrap your call in a function:
function startAJAX(thunk, bar, callback) {
$http.get('/api/v1/foo/userinfo?thunk='+thunk+'&bar='+bar).success(function(data) {
callback(data.id);
});
}
Then make the call and do your next http call:
startAJAX(thunk, bar, function(id) {
$http(id).....
});
});

Using a watch() method isn't necessary. Use callbacks, or if you want to be fancy use promises to keep things organized.
var callOnePromise = $http.get('/api/foo');
var callTwoPromise;
callOnePromise.success(function(data) {
callTwoPromise = $http.get('/api/bar/' + data.id);
});
callTwoPromise.success(function() {
//Cool stuff here.
});

Related

Passing value in function properly in AngularJS

I have the following function which takes variable description as parameter
$scope.relsingle = function(description) {
console.log(description);
var url = $scope.url+'/api/descrelation?limit=4&description='+description;
$http.get(url).success(function(data) {
console.log(data);
$scope.apgresponse = data;
})
};
I use the following approach to pass this value in the html page
ng-init="relsingle(prodres[0].description)"
This value of prodres[0].description comes from here.
And value of prodres comes from here
$scope.prodat = function(id) {
var uri = $scope.url+'/api/getproduct?productid='+id;
console.log(uri);
$http.get(uri).success(function(data) {
console.log(id);
console.log(data);
$scope.prodres = data;
})
};
when i log the value of description in console in the relsingle function.
console.log(description);
This gives me value undefined.
You can't do it like this with ngInit because it runs only once and when it happence variable prodres is not yet available because it comes from async call.
What you can however do is to make ngInit execute only after the value for prodres has been resolved:
<div ng-if="prodres" ng-init="relsingle(prodres[0].description)">...</div>
Because ngIf has higher priority ngInit will execute only after ngIf.
Well it is because it is because the array has not been evaluated in javascript.Use a call back function and store that array in a variable on the $scope scope.Then you can use it in the function

AngularJs interval only shows {{name}}

I'm trying to get a list of all the 'cashflow' objects in my django application by calling a AngularJS get function every 5 seconds. I run the function with $interval(getCashflows, 5000); in my js file and try to display it in my html as [[getCashflows]] (see interpolateprovider)
Now the only thing I get is "[[getCashflows]]" in my html.. does interpolateProvider not work or do I need to call it differently?
app = angular.module("coco",[]);
app.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
});
app.controller('cocoCtrl',['$scope','$http', function($scope) {
$scope.save = function (cashflow) {
var dataObj = {
value : cashflow.value,
date : cashflow.date,
};
$.ajax({
url : "/create_cashflow/", // view functie
type : "POST",
data : dataObj,
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
success : function(json) {
$(".data").prepend("<li><strong>"+json.value+"</strong> - <em> "+json.date+"</em></li>");
}
});
}
}]);
app.controller('cocogetCtrl',['$scope','$http', function($scope,$http, $interval) {
$scope.cashflows = "";
$interval($scope.getCashflows = function() {
return $http.get("/get_cashflows/", {data:data}).then(function(response) {
$scope.cashflows = "test";
alert(response.toString());
$(".flows").prepend("<li><strong>"+json.value+"</strong> - <em> "+json.date+"</em></li>");
return response.toString();
});
}, 5000);
}]);
Your problem is almost certainly that you are attempting to update an angular scope variable from a jQuery callback. Angular only checks for changes to the scope inside its own digest loops and the callback will happen outside that context so angular doesn't see the change.
The simple fix is to stop using $.ajax() calls and start using the $http service that you have already included in your controller.
However it isn't at all clear what you expect to see in your html. The function getCashflows isn't returning a value, either as written or indeed if you rewrite it to use $http. The value is retrieved from the server asynchronously. You should change it so that the scope value is a promise which resolves to the expected value. As $http already returns a promise it should be sufficient to do something like:
function getCashflows() {
$scope.cashFlows = $http.get("/get_cashflows/", {data:data})
.then(function(response) {
return response.data;
});
}
The change your html to interpolate the value cashFlows instead of the function.
There is probably no reason for getCashflows itself to be exposed to the scope, you could just make it an ordinary function which will have the side effect of fixing the call to $interval that will currently just cause the javascript to stop due to an unresolved name.

Pass var to angular $resource success function

I've been going crazy over this and I think the answer is probably out there but I don't know the right way to ask Google the question.
Essentially I need a way to make a $resource call, and pass in some data that I want to then use in the success function.
app.controller('VariantListController', ['djResource', function(djResource){
var Variants = djResource('/ship-builder/variants/?format=json');
var Vehicle = djResource('/ship-builder/vehicles/:id', {id: '#id'});
this.variants = Variants.query(function(variants){
$(variants).each(function(){
console.log(this);
variantData = this;
var vehicleData = Vehicle.get({id:this.baseVehicle}, function(){
console.log(variantData);
})
})
});
}]);
In the above example, in the innermost success function, 'variantData' is always the value of the LAST entry from the previous level. This makes sense because the value was set by the last item in the array long before the success happens. I need a way though to have the value of the 'variantData' that was inexistince when the Vehicle.get() was called.
Does that make sense? I find it very hard to explain the issue.
You need to create a closure to make it work. Something like
this.variants = Variants.query(function(variants){
$(variants).each(function(){
getVehicleData(this);
})
});
function getVehicalData(variantData) {
var vehicleData = Vehicle.get({id:variantData.vehicleId}, function(){
console.log(variantData);
})
}
I am by no means an expert on the $resource service, but perhaps using the $promise.then method instead of the success callback would work.
$(variants).each(function(){
console.log(this);
variantData = this;
Vehicle.get({id:this.baseVehicle}).$promise.then(function() {
console.log(variantData);
});
});
Since the value in variantData may change before the success callback is actually called, you want to ensure the the callback has the original value stored.
var vehicleData = Vehicle.get({id:this.baseVehicle}, function(vData){
return function() {
console.log(vData);
}
}(variantData));
The above will create a new function with variantData stored in a closure.

angularjs this is undefined while using $.proxy

I have an UserApplications object wich queries the server for a list of applications the user is registered to looking like this:
data.factory('UserApplications', function($resource){
return $resource('/users-rs/api/getapplications/:locale',{},{
query: {method: 'GET', params: {locale: 'locale'}, isArray: true}
});
});
I call it in another service and want to save the data as a JSON string using the angular-localstorageservice module (https://github.com/grevory/angular-local-storage) which is passed to the constructor of the service like this:
function UserService(UserInfoData, localStorageService, UserApplications){
this.UserInfoData = UserInfoData;
this.localStorageService = localStorageService;
this.userApplications = UserApplications;
}
When I give a callback function to the $resource.query() function and wrap it with $.proxy I keep getting this.localstorag is undefined, when I debug it this is a reference to window. So not exactly the behaviour I expected.
Is there any other way to pass 'this' or a reference to the object to the callback function?
I've allready tried with creating a variable with a reference to this but it doesn't do the trick either :/
UserService.prototype.getUserApplications = function(){
var locale = this.getUserinfoLocale();
var applications = this.localStorageService.get(Constants.key_applications+locale);
if(applications !== null){
return JSON.parse(applications);
} else {
return this.userApplications.query({locale: locale}, $.proxy(function(data, locale){
this.localStorageService.add(Constants.key_applications+locale, JSON.stringify(data));
}), this);
}
};
I think you missed the comma position and is sending "this" to userApplications' query method, not jQuery's proxy one.
Try this in your "else" block instead:
return this.userApplications.query({locale: locale}, $.proxy(function(data, locale){
this.localStorageService.add(Constants.key_applications+locale, JSON.stringify(data));
}, this));

Why is my controller property 'undefined' when I assign it the result of $resource query()?

I have a JSON data structure:
[
{
"title" :"a1",
"id" :"b1",
"name" :"c1"
},
{
"title" :"a2",
"id" :"b2",
"name" :"c2"
}
]
I am accessing is as an external JSON and parsed through a factory method. I want it to assign it to a Javascript variable in my controller.
function Control($scope,data)
{
var e=data.query(); /* getting the external JSON data */
alert(e[0].title);
}
It says that e[0] is undefined. Is there any other way I can assign it to a Javascript variable and then traverse through it? Please help.
Most likely, #Marty is correct. If you are using the query() method from the $resource service, it is asynchronous. This will likely do what you want:
data.query( function( data ) {
var e = data;
alert(e[0].title);
});
Okay, so $resource can be confusing like this... It immediately gives you a reference to the return object, but doesn't update the object until the asynchronous AJAX call returns... so...
If you put your return value from data.query() in a property on $scope, since it's $watched when you bind it in your view, you'll see it update. HOWEVER, if you're just trying to alert it, it will alert the value before it's been updated.. again because of the async aspect of $resource.
Otherwise, you can get the value the way that #MarkRajcok has shown in his answer.
Here is a psuedo-code illustration of ways you can use $resource query();
app.controller('FooCtrl', function($scope, $resource) {
var Bar = $resource('/Bar/:id', {id: '#id'});
// here, we get the result reference and stick it in the scope,
// relying on a digest to update the value on our screen.
$scope.data = Bar.query();
//OR
//here we already have a reference.
var test = Bar.query(function() {
//in here, test has been populated.
$scope.data2 = test;
});
alert(test); //not populated here, yet.
//OR
Bar.query(function(x) {
$scope.data3 = x;
});
});
This is all done so the object(s) returned can have functions pre-instantiated on them like $save(), etc.

Categories