Is there a way to call an unknown amount of API calls to a URL via the get()
function in AngularJS and add those all into a model ($scope
variable). What I've done thus far is the following:
if(theUIDS != "") {
var myDropbox = [];
for(i = 0; i < theUIDS.length; i++) {
var temp = {};
temp.uid = theUIDS[i];
$http({ url: '/dropbox/accounts/get', method: 'GET', params: { uid: theUIDS[i] }}).success(function(acctData) {
temp.accountInfo = acctData;
});
$http({ url: '/dropbox/files/get', method: 'GET', params: { uid: theUIDS[i] }}).success(function(fileData) {
temp.files = fileData;
});
myDropbox.push(temp);
}
$scope.dropboxAccounts = myDropbox;
}
I check if there are any UID's and for each one I create a temp
object which is populated with a uid
, then an accountInfo
object, and then a files
object. After I set up my temp
object, I push it onto the myDropbox
array. Once the loop has finished, I set the dropboxAccounts model to the myDropbox
variable in $scope
. I'm new to Angular, but I'm pretty sure this is at least the right idea. Luckily I'm getting the following data in correct order:
{"uid":"332879"}
{"uid":"155478421",
"accountInfo":{
"country":"US",
"display_name":"Patrick Cason",
"name":"Second Dropbox",
"quota_normal":1174504,
"quota_shared":0,
"quota_total":2147483648,
"referral_link":"https://www.dropbox.com/referrals/NTE1NTQ3ODQyMTk?src=app9-203957",
"uid":155478421},
"files":[{
"created_at":"2013-04-17T15:13:46Z",
"directory":true,
"dropbox_user_id":26,
"fileType":"Folder",
"id":198,
"name":"Photos",
"path":"/Photos",
"rev":"10edb44f9",
"size":"-",
"updated_at":"2013-04-17T15:13:46Z"}]
}
The strange thing is that only one of my UID's gets updated. I know that the loop is correctly going through because I have two UID's and if I alert at the beginning the loop I get two loops. The reason I think the second isn't being populated is because the push statement isn't waiting for both of the promises to go through. How can I ensure that I wait for each of the AJAX calls to finish before assigning myDropbox
to the $scope
variable?
I'm pretty new to AngularJS, so this solution is very much so a work-in-progress. I figure that since I've struggled through learning more about it that other people may be in the same position as well. With that said, I'm going to not only post my answer, but also explain my thinking behind the code. I'd love to get any feedback if anyone feels the answer could be improved any.
Here's the code I used to get everything working:
var app = angular.module('myApp', []);
app.controller('DropboxCtrl', function($scope, dropbox) {
$scope.dropboxAccounts = dropbox.getAccounts();
$scope.dropboxFiles = dropbox.getFiles();
});
app.factory('dropbox', function($http, $q) {
var theUIDS = [12345,67890];
return {
getAccounts: function() {
var promises = [];
for(i = 0; i < theUIDS.length; i++) {
promises.push($http({
url: '/dropbox/accounts/get',
method: "GET",
params: { uid: theUIDS[i] }
}));
}
return $q.all(promises);
},
getFiles: function() {
var promises = [];
for(i = 0; i < theUIDS.length; i++) {
promises.push($http({
url: '/dropbox/files/get',
method: "GET",
params: { uid: theUIDS[i] }
}));
}
return $q.all(promises);
}
}
});
We start by declaring a module myApp
and saving it in a variable app
... notice the empty array we're passing which would normally be a parameter for any further requirements which may or may not be inherited from other modules.
After our module is declared we need to create a corresponding controller which will be a gateway for all interactions to take place. In this case we need access to the $scope
variable which is relative to our controller (not relative to the app itself). We also declare what factory this controller is related to, in my case it's dropbox
(we'll get to factories in a moment). Inside of this controller we assign two models to $scope
: dropboxAccounts
and dropboxFiles
. Note that my original desire was to have one model within my AngularJS app. While this is possible... I opted against it because I found it difficult to differentiate my two types of JSON returns apart. One returns account metadata and the other returns an array of files of that account. I would have liked to have all these under one model and be sorted by a uid
parameter, but found this to be impossible to do without changing what JSON my RESTful endpoints output. In the end, I opted for two separate models so I can work with them easier (until I find a way to combine them according to one common parameter).
Lastly, we create a factory which stores my AJAX functions (using $http
for the actual AJAX call, and $q
for handling the promises). I have two functions: (which remember are called from my controller) getAccounts
and getFiles
. Each of them has an array called promises which will store the promises of my $http
calls. I run through these calls in a for-loop which will look at each of my items in theUIDS
, which is used in my AJAX call, and is then pushed onto the promises
array. At the end we have our $q
which will wait until all the AJAX calls in the promises
array has finished successfully before returning all that data in one big promise back to our controller and assigning it to $scope
.
AngularJS is really tough. This particular issue has taken me two days of debugging and trying again and again. I have been told that while the learning curve to this front-end MVC framework is pretty steep, the payoff is well worth it. I suppose we shall see...
all
methodIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With