AngularJS and $http get JSON - data is not defined - javascript

Hi I am trying to retrieve some data from webservice using AngularJS $http get.
I have the following code snippet:
In the servicesjs:
.factory('BoothDesignatedCoordsService', ['$http', function ($http) {
var factory = {};
factory.getBoothDesignatedCoords = function (strBoothName, intFloorPlanID) {
var sendToWS;
var boothDesignatedCoords
var JSONObj = {
BoothName: strBoothName,
FloorPlanID: intFloorPlanID
};
sendToWS = JSON.stringify(JSONObj)
var urlBase = 'http://localhost:4951/wsIPS.asmx/fnGetBoothDesignatedCoords?objJSONRequest=' + sendToWS;
return $http.get(urlBase)
}
return factory;
}])
In the controllerjs:
var boothDesignatedCoords = BoothDesignatedCoordsService.getBoothDesignatedCoords(strListShortListedBooth[i], 3).success(function (response, data, status) {
console.log("successfully send booth name and floor plan id to ws");
console.log("data " + data + " , status : " + status);
console.log("data " + data);
boothDesignatedCoords = data;
for (var c = 0; c < boothDesignatedCoords.length; c += 2) {
}
The $http get is successful as I am able to print "successfully send booth name and floor plan id to ws" in the browser console log.
When I tried to print console.log("data " + data), it gives me some values of an integer array. That is exactly what I want. But in the controller I tried to assign data to the variable boothDesignatedCoords, the program does not run the for loop. Am I missing some code?
EDIT:
I tried to trace the code ( trace the variable called "data" in the controllerjs) and it says "data is not defined"

You appear to be confused about the methods available on the $http promise and their arguments. Try this
BoothDesignatedCoordsService.getBoothDesignatedCoords(strListShortListedBooth[i], 3)
.then(function(response) {
var data = response.data
var status = response.status
console.log('data', data) // note, no string concatenation
// and so on...
})
FYI, the success and error methods have been deprecated for some time and removed from v1.6.0 onwards. Don't use them.
I also highly recommend passing query parameters via the params config object
var urlBase = 'http://localhost:4951/wsIPS.asmx/fnGetBoothDesignatedCoords'
return $http.get(urlBase, {
params: { objJSONRequest: sendToWS }
})
This will ensure the key and value are correctly encoded.

Related

Angular making pseudo-synchronous HTTP requests

I want to construct a mechanism that would access a database via POST requests. So far, I do received the desired data, but am have issues with the timing. Here are three pieces of code that I'm using (simplified to keep the focus of the question).
First, a factory handling the HTTP request vis-à-vis a servlet:
var My_Web = angular.module('My_Web');
My_Web.factory('DB_Services', function($http , $q) {
var l_Result ;
var DB_Services = function(p_Query) {
var deferred = $q.defer();
var url = "http://localhost:8080/demo/servlets/servlet/Test_ui?";
var params = "data=" + p_Query ;
var Sending = url + params ;
$http.post(Sending).
success(function(data, status, headers, config) {
deferred.resolve(data);
}).
error(function(data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
return DB_Services;
});
Second, a general purpose function handling the promise (or so I meant) exposed to all the controllers that would need to extract data from the remote DB:
$rootScope.Get_Data_from_DB = function(p_Query) {
DB_Services(p_Query).then(function(d) {
console.log("In Get_Data_from_DB; Received data is: " + JSON.stringify(d));
$scope.data = d;
});
};
Third, one example within one of the controllers:
$scope.Search_Lookups = function () {
console.log ("search for lookup data...") ;
var l_Lookup_Type = document.getElementById("THISONE").value ;
var l_Send_Request_Data = '{"Requestor_ID":"4321" , "Request_Details" : { "Data_type" : "' + l_Lookup_Type + '" } }' ;
console.log("Sending Request: " + l_Send_Request_Data) ;
l_Data = $rootScope.Get_Data_from_DB(p_Query) ;
console.log ("Received response: " + l_Data) ;
Deploy_data(l_Data) ;
}
The function Deploy_data(l_Data) is responsible of dismembering the received data and put the relevant pieces on screen.
What happens is that I get on the console the string Received response: undefined and immediately after the result of the retrieval as In Get_Data_from_DB; Received data is: (here I get the data).
The Received response: undefined is printed from the invoking function (third piece of code), whereas the output with the actual data is received and printed from within the second piece of code above. This means that the invocation to Deploy_data would not receive the extracted data.
Once again, the same mechanism (i.e. the factory $rootScope.Get_Data_from_DB) would be vastly used by many controllers.
I thought of using $scope.$watch but I'm not sure because the same user might be triggering several queries at the same time (e.g. request a report that might take few seconds to arrive and, in the meantime, ask for something else).
I think I found a solution (at least it appears to be ok for the time being). The global function Get_Data_from_DB accepts a second parameter which is a callback of the invoking controller.
The invoking controller creates a private instance of the Get_Data_from_DB function and triggers a request providing the callback function.
I'll need to test this with parallel queries, but that is still a long way to go...

ng-repeat not listing movie titles

I'm trying to create a simple movie app in Angular. I can do a JSON request to the tmdb (the movie database) api and show the raw result on my homepage. But my problem is that I can't seem to only show the title of the movies from the JSON request.
examplecontroller.js.coffee
angular.module('app.exampleApp').controller('exampleCtrl', [
'$scope', '$http', function($scope, $http) {
var base = 'http://api.themoviedb.org/3';
var service = '/movie/popular';
var apiKey = 'a8f703963***065942cd8a28d7cadad4';
var callback = 'JSON_CALLBACK'; // provided by angular.js
var url = base + service + '?api_key=' + apiKey + '&callback=' + callback;
$scope.movieList = 'requesting...';
$http.jsonp(url).then(function(data, status) {
$scope.movieList = JSON.stringify(data);
console.log($scope.movieList)
},function(data, status) {
$scope.movieList = JSON.stringify(data);
});
}
]);
show.html.haml
#search{"ng-app" => "app.exampleApp"}
%div{"ng-controller" => "exampleCtrl"}
%div{"ng-repeat" => "movie in movieList track by $index"}
{{movie.title}}
When I check the elements in Chrome I see that I have about 25.000 ng-repeat divs. But all without content.
I've been following this tutorial for a bit (and some other sources) and something I don't understand is the movie in Movielist. I know that movielist is the whole json request but what is movie?
Solved
controller
angular.module('app.exampleApp').controller('exampleCtrl', [
'$scope', '$http', function($scope, $http) {
var base = 'http://api.themoviedb.org/3';
var service = '/movie/popular';
var apiKey = 'a8f7039633f2065942cd8a28d7cadad4';
var callback = 'JSON_CALLBACK'; // provided by angular.js
var url = base + service + '?api_key=' + apiKey + '&callback=' + callback;
$scope.movieList = [];
$http.jsonp(url).
success(function (data, status, headers, config) {
if (status == 200) {
$scope.movieList = data.results;
console.log($scope.movieList)
} else {
console.error('Error happened while getting the movie list.')
}
}).
error(function (data, status, headers, config) {
console.error('Error happened while getting the movie list.')
});
}
]);
show
%h1
Logo
%li
= link_to('Logout', destroy_user_session_path, :method => :delete)
#search{"ng-app" => "app.exampleApp"}
%div{"ng-controller" => "exampleCtrl"}
%div{"ng-repeat" => "movie in movieList"}
{{ movie.original_title }}
Your problem is you are taking the javascript array returned to the request callback as data and converting it into a string using JSON.stringify().
Then when you pass this string to ng-repeat it is looping over every character in that string. Thus you have a huge number of repeated <div> but since each is a string containing one character there is no title property of that string to print
Pass the array directly to your scope variable in the request callback.
Change:
$scope.movieList = JSON.stringify(data);
To:
$scope.movieList = data;
JSON is a string data format. When $http receives that string response it will internally parse it to a javascript object/array. You should not need to transform it yourself

Javascript Variables Not Globally Returning / Adding Together

I'm trying to add both Facebook and Twitter share counters together, however all my efforts have failed.
<script>
tweets = 0;
function getTwitterCount(url){
$.getJSON('http://urls.api.twitter.com/1/urls/count.json?url=' + url + '&callback=?', function(data){
tweets = data.count;
$('#twitterCount').html(tweets);
return true;
});
}
var urlBase='http://abcdfav4.com/About/KickStarterCampaign/Rewards/ThePeaceSensation.html';
getTwitterCount(urlBase);
$.ajax({
type: 'GET',
url: 'https://graph.facebook.com/http://abcdfav4.com/About/KickStarterCampaign/Rewards/ThePeaceSensation.html',
success: function(data) {
showCount(data);
}
});
var fbshares = 0;
function showCount(responseText) {
// Save the parsed JSON
var json = responseText;
// Check if the response contains a 'shares' property
// If it doesn't, we can just exit this function
if (!json.hasOwnProperty('shares'))
return;
// A shares property and value must exist, update
// the span element with the share count
fbshares = json.shares;
$('#fb-share-count').html(fbshares);
}
var TotalShares = tweets + fbshares;
$('#total-share-count').html(TotalShares);
</script>
I could really do with some outside insight as I've been working crazy to get this website up and running ASAP and I'm probably overlooking the most obvious of things...
Console Log Reads:
Uncaught ReferenceError: fbshares is not defined
sdk.js:64 Invalid App Id: Must be a number or numeric string representing the application id.
card.html?v=2:79 Uncaught ReferenceError: I18n is not defined
sdk.js:64 FB.getLoginStatus() called before calling FB.init().
However despite this message, the Facebook and Twitter counters are working 100%, I just cannot get them to add together.
Best Regards,
Tim
Here's a solution:
var tweets;
function getTwitterCount(url) {
$.getJSON('http://urls.api.twitter.com/1/urls/count.json?url=' + url + '&callback=?', function(data) {
tweets = data.count;
$('#twitterCount').html(tweets);
showTotal();
});
}
var urlBase = 'http://abcdfav4.com/About/KickStarterCampaign/Rewards/ThePeaceSensation.html';
getTwitterCount(urlBase);
$.ajax({
type: 'GET',
url: 'https://graph.facebook.com/http://abcdfav4.com/About/KickStarterCampaign/Rewards/ThePeaceSensation.html',
success: showCount
});
var fbshares;
function showCount(responseText) {
// Save the parsed JSON
var json = responseText;
// Check if the response contains a 'shares' property
// If it doesn't, we can just exit this function
if (!json.hasOwnProperty('shares'))
return;
// A shares property and value must exist, update
// the span element with the share count
fbshares = json.shares;
$('#fb-share-count').html(fbshares);
showTotal();
}
function showTotal() {
if (tweets !== undefined && fbshares !== undefined)
$('#total-share-count').html(tweets + fbshares);
}
Basically showTotal attempts to sum the two values after each callback. When both values are defined, it will place the sum into the HTML.

Creating a callback to return an array from a function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I am trying to learn Node.js
I am having trouble creating my own call back on a function. It seems like such a simple thing but I don't quite understand how to do it.
The function is passed an address (example: "1234 will ln, co") which uses google's geolocate json api to return the full address, latitude and longitude in an array.
Here is my code:
//require secure http module
var https = require("https");
//My google API key
var googleApiKey = "my_private_api_key";
//error function
function printError(error) {
console.error(error.message);
}
function locate(address) {
//accept an address as an argument to geolocate
//replace spaces in the address string with + charectors to make string browser compatiable
address = address.split(' ').join('+');
//var geolocate is the url to get our json object from google's geolocate api
var geolocate = "https://maps.googleapis.com/maps/api/geocode/json?key=";
geolocate += googleApiKey + "&address=" + address;
var reqeust = https.get(geolocate, function (response){
//create empty variable to store response stream
var responsestream = "";
response.on('data', function (chunk){
responsestream += chunk;
}); //end response on data
response.on('end', function (){
if (response.statusCode === 200){
try {
var location = JSON.parse(responsestream);
var fullLocation = {
"address" : location.results[0].formatted_address,
"cord" : location.results[0].geometry.location.lat + "," + location.results[0].geometry.location.lng
};
return fullLocation;
} catch(error) {
printError(error);
}
} else {
printError({ message: "There was an error with Google's Geolocate. Please contact system administrator"});
}
}); //end response on end
}); //end https get request
} //end locate function
So when I try to execute my function
var testing = locate("7678 old spec rd");
console.dir(testing);
The console logs undefined because its not waiting for the return from locate (or at least I am guessing this is the problem).
How do i create a call back so when the locate function returns my array, it runs the console.dir on the array it returned.
Thanks! I hope my question makes sense, im self taught so my tech jargon is horrible.
You need to pass in the callback function to your method - so the callback might look something like this
function logResult(fullLocation){
console.log(fullLocation)
}
You would pass this in to your locate method along with the input:
// note: no parentheses, you're passing a reference to the method itself,
// not executing the method
locate("1234 will ln, co",logResult)
You can also do this inline - much like the response object you're already dealing with:
locate("1234 will ln, co",function(fullLocation){
// do something useful here
})
Now for the bit inside your method, instead of trying to return the result you just call the callback with the result:
function locate(address, callback) {
......
response.on('end', function (){
if (response.statusCode === 200){
try {
var location = JSON.parse(responsestream);
var fullLocation = {
"address" : location.results[0].formatted_address,
"cord" : location.results[0].geometry.location.lat + "," + location.results[0].geometry.location.lng
};
callback(fullLocation); // <-- here!!!
} catch(error) {
printError(error);
}
} else {
printError({ message: "There was an error with Google's Geolocate. Please contact system administrator"});
}
}); //end response on end
.....
}

Generating and saving a list of ParseObjects within a Parse.Cloud.httpRequest in a cloud function

So, I'm defining a cloud function that's supposed to make a call to the foursquare api and generate a list of restaurants (each restaurant is a ParseObject) from the returned JSON. I successfully do this, but I run into problems when trying to save these objects to my database and send them back to my phone by calling response.success(). The large code block below saves the list to my database, but if I try
Parse.Object.saveAll(restaurants)
response.success(restaurants)
I end the function before all of the restaurants are saved. I tried using this line instead
Parse.Object.saveAll(restaurants).then(response.success(restaurants))
, but only half of the restaurants get saved before I get the error "Failed with: Uncaught Tried to save an object with a pointer to a new, unsaved object." I also get this error if I call response.success(restaurants) without attempting to save the list. I read that this is a bug in parse preventing someone from printing or passing unsaved ParseObjects. Any ideas? I also tried using .then on the http request, but I get the same issues or a new error: "com.parse.ParseException: i/o failure: java.net.SocketTimeoutException: Read timed out. "
Parse.Cloud.define("callFourSquare", function(request, response) {
//The Parse GeoPoint with current location for search
var geo = request.params.location;
var geoJson = geo.toJSON();
var url = "https://api.foursquare.com/v2/venues/explore?ll=" + geoJson.latitude + ","
+ geoJson.longitude + "&section=food&sortByDistance=1&limit=50&venuePhotos=1&categoryId=4d4b7105d754a06374d81259&client_id= C043AJBWKIPBAXOHLPA0T40SG5L0GGMQRWQCCIKTRRVLFPTH"
+ "&client_secret=Y1GZZRHXEW1I3SQL3LTHQFNIZRDCTRG12FVIQI5QGUX0VIZP&v=20140715";
console.log(url);
//Call to FourSquare api, which returns list of restaurants and their details
Parse.Cloud.httpRequest({
method: "GET",
url: url,
success: function (httpResponse) {
var restaurants = [];
var json = httpResponse.data;
var venues = json.response.groups[0].items;
console.log(venues.length)
for(i = 0; i < venues.length; i++) {
venue = venues[i].venue;
var RestaurantObject = Parse.Object.extend("Restaurant");
var rest = new RestaurantObject();
try {
rest.set("geoLocation",
new Parse.GeoPoint({latitude: venue.location.lat,
longitude: venue.location.lng}));
} catch(err) {}
try {
rest.set("address", venue.location.address + " " + venue.location.formattedAddress[1]);
} catch(err) {}
try {
rest.set("phoneNumber", venue.contact.formattedPhone);
} catch(err) {}
try {
rest.set("website", venue.url);
} catch(err) {}
rest.set("name", venue.name);
rest.set("lowerName", venue.name.toLowerCase());
try {
rest.set("priceLevel", venue.price.tier);
} catch(err) {}
try {
rest.set("rating", venue.rating/2);
} catch(err) {}
try {
rest.set("storeId", venue.id);
} catch(err) {}
try {
rest.set("icon", venue.photos.groups[0].items[0].prefix + "original"
+ venue.photos.groups[0].items[0].suffix)
} catch(err) {}
restaurants.push(rest);
}
Parse.Object.saveAll(restaurants);
},
error: function (httpResponse) {
response.error("Request failed with response code:" + httpResponse.status + " Message: "
+ httpResponse.text);
}
});
});
I believe your issue is that you aren't returning the Promise from Parse.Object.saveAll(restaurants) when your httpRequest() is complete. Try returning that saveAll() promise and see if it completes.

Categories