I'm using an Angular HTTP Resource to get some data from an API. The method on the API is actually a PUT, but returns an array of data. (Note, it's not my API)
It performs the HTTP Call perfectly and I can see in the Network on Google Developer Tools my response is right. However, I keep getting "TypeError: undefined is not a function" when trying to work with the response data.
Here are some of the different methods I've tried and each one gives the same TypeError:
HTTP Resource
.factory('Sports', ['$resource', 'SPORTS_CONFIG',
function($resource, SPORTS_CONFIG) {
return $resource(SPORTS_CONFIG.URL, {}, {
get: {
method: 'PUT',
isArray: true
}
});
}
])
Angular JS Attempts
// Construct Sports Body
var s = new Sports($scope.sport);
// Attempt 1
s.$get({}, function(data){
});
// Attempt 2
s.$get({}).then(function(data){
});
// Attempt 3
s.$get({}).$promise.then(data){
});
EDIT
After looking at my error code more, it looks like the error is occurring on 'isArray' in my HTTP Resource. When I set isArray to false, it errors because it expects an object but gets an array. When I keep it true, it errors and says TypeError: undefined is not a function. When I click the javascript line it's 'isArray'.
SECOND EDIT
I've gotten it to work using the following code:
$scope.teams = Sports.get($scope.sport);
However, $scope.teams = [0, $promise, $resolved] . How can I only get [0] instead of the $promise and $resolved?
the argument to your 'then' function should itself be a function.
eg:
s.$get({}).then(function (data){
});
Your syntax looks wrong, follow this approach instead:
$http.get('/someurl').then(function(response) {
//do something with response.data;
}, function(errResponse) {
console.error('Error while fetching data');
});
As you can see you should be passing in a function which passes in the response from the server, and then you can get at your data.
You can try something like this (with a function)
$http({
method : "GET",
url : "your_url"
}).success(function(data, status, headers, config) {
$scope.yourVariable= data;
}).error(function(data, status, headers, config) {
alert("Request failed. HTTP status:" + status);
});
Due to the edit above, this answer became outdated.
As I cannot comment right now, the way to get the just first item as you'd like is simple:
$scope.teams = Sports.get($scope.sport)[0];
Related
I am getting a valid JSON request but only $http fail method is invoked. It shows OK 200 in firebug. Also the view is not getting updated. Newbie trying out AngularJS so something could be too wrong :)
$http.jsonp("http://localhost:51377/api/Books/1").success(function(data, status, headers, config) {
alert("Suc");
$scope.people = data;
}).error(function(data, status, headers, config) {
$scope.people = data;
alert("fail");
});
This is the response in firebug:
{"ID":1,"BookName":"ASP.Net"}
Also fails for:
[{"ID":1,"BookName":"ASP.Net"}]
getting 404 in status code in $http call. I am using jsonp which should take care CORS? as I read from somewhere. My angular is in file:// protocol
Update-1:
Tried with launching my angular in localhost from VS. Same results
Update-2:
I added configuration changes to remove CORS in my backend .net webapi and now it works with the following code but still the original above code using jsonp fails
$http({
method: 'get',
url: 'http://localhost:51377/api/Books/',
responseType: "json"
}).success(function (data, status, headers, config) {
alert(data);
console.log('Success: ' + data);
$scope.people = data;
}).error(function (data, status, headers, config) {
console.log('Error: ' + data);
});
I believe you need to add a callback parameter to your request:
$http.jsonp("http://localhost:51377/api/Books/1?callback=JSON_CALLBACK")
More info here:
https://docs.angularjs.org/api/ng/service/%24http#jsonp
Also, see this JSFiddle (not mine):
http://jsfiddle.net/saarmstrong/hYACX/8/light/
When you remove the callback parameter it fails...
try to use only "/api/Books/1" instead of "http://localhost:51377/api/Books/1"
I'm posting successfully to my server , however when requests fails the error object is empty and i cannot construct logic based on the error code
Here is the code and what i see on DEV tools
$http({
method: 'POST',
url: 'my remote api/',
data: {'Account' : $scope.userPhoneNumber, 'Initiator' : initiator.toString()},
headers: {"Authorization": "Basic register:register"}
}).
then(function (response) {
console.log(response.data.AuthenticationUid);
openModalWindow(initiator, response.data.AuthenticationUid);
}, function (data) {
console.log(data);
$scope.phoneNotFound = true;
});
As you can see the printed data object shows status as -1 while it should show 404....
The console output indicates that you are not successfully POSTing to the server. Your OPTIONS request is successful, but your post fails due to missing 'Access-Control-Allow-Origin' headers which is indicative of a CORs error.
Without knowledge of your server it's a bit hard to give you an exact solution, but searching for something along the lines of 'setting up CORS in ' should get you on the right track.
I'm trying to use a resource to save some data, and am getting something strange happen:
here is the code:
var appointment = new Appointment(formData);
console.log(appointment);
appointment.$save().success(function (data, status, headers, config){
console.log(data);
$state.transitionTo('form.success');
});
now the wierd thing is that the data is saving so the $save function is working, but I'm getting undefined is not a function errors, and the success callback isnt working - does anyone know why?
The resource for the Appointments is:
angular.module('MyApp')
.factory('Appointment', function($resource){
return $resource('/api/admin/:id', { id: "#_id" }, {
query: {method:'GET', isArray:true}
});
})
and I'm using this and its inherent $save function, so it shouldn't be a problem - also it seems to be the callback thats not working - the save is adding data no problem
SOLUTION:
I simplified it by just doing:
appointment.$save(function(data){
//stuff here for the callback works
});
also I think that using the promise method .then would work, but I didn't try it.
I marked it as accepted anyway for good karma!
Thanks
The success function is specific to the $http service:
The $http service is a function which takes a single argument — a configuration object — that is used to generate an HTTP request and returns a promise with two $http specific methods: success and error.
The $save method returns a regular promise, so you can use then instead:
appointment.$save().then(function (data, status, headers, config){
console.log(data);
$state.transitionTo('form.success');
});
I need to do some cross site scripting. The block of code below contains the method of jsonp, the method returns as if it failed, but when I change it to be a get request I then have success. I need to be able to a successful response using the jsonp method. The following can be ruled out. The response is valid json and this param is in the url ?callback=JSON_CALLBACK. Here is the json I receive from doing the http request and the code block that executes this code.
http response status code 200
[{"cube":"1" ,"points":"160"},{"cube":"2","points":"690"},{"cube":"3","points":"331"}]
code block
var myApp = angular.module('test', []);
myApp.controller('UserCtrl', function($scope, users) {
$scope.usersPerCube = users.getUsers();
})
myApp.factory('users', function($http) {
return {
getUsers: function() {
var deferred = $q.defer();
var url = "http://localhost/api/api/index.php/analytics/UsersPerCube?callback=JSON_CALLBACK";
$http.get(url).success(function (data, status, headers, config) {
console.log(data);
deferred.resolve(data);
}).error(function (data, status, headers, config) {
//this always gets called
console.log(status);
deferred.reject(status);
});
return deferred.promise;
}
}
Note that I have edited my server side code and now receive
"angular.callbacks._1( {"cube":"1","points":"160"},{"cube":"2","points":"690"},{"cube":"3","points":"331"})"
UPDATE
The above is valid and now the success method is executing. I just need to figure out how to parse the objects. I will post again once I figure out the answer.
I have decided to give a detailed description of how to do a jsonp request so others will not run into the same troubles as I did.
myApp.factory('users', function($http) {
return {
getUsers: function() {
var deferred = $q.defer();
var url = "http://localhost/api/api/index.php/analytics/UsersPerCube?callback=JSON_CALLBACK";
$http.get(url).success(function (data, status, headers, config) {
console.log(data);
deferred.resolve(data);
}).error(function (data, status, headers, config) {
//this always gets called
console.log(status);
deferred.reject(status);
});
return deferred.promise;
}
Notice that the url contains ?callback=JSON_CALLBACK. Here is a nice stackoverflow on that. Once you get the response then you'll receive a json like the one below.
"angular.callbacks._1( {"cube":"1","points":"160"},{"cube":"2","points":"690"},{"cube":"3","points":"331"})"
Here is a nice stackoverflow on that subject
Now the one part that got me is that the server has to return the GET param, callback. Here is a good tutorial for that. http://niryariv.wordpress.com/2009/05/05/jsonp-quickly/ So the json looks like the one above.
Well, I hope this helps someone in the future.
If you want to make several JSONP requests through $http service, you should use a little hack. Agular change JSON_CALLBACK to internal value, and best way to use next solution: put this js code into your returned js-file:
var callbackId = '_' + (angular.callbacks.counter - 1).toString(36);
angular.callbacks[callbackId](/* YOUR JSON */);
To be sure that this code will work for you, please check createHttpBackend method in angular sources.
I am using angular's $http.jsonp() request which is successfully returning json wrapped in a function:
var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=jsonp_callback";
$http.jsonp(url).
success(function(data, status, headers, config) {
//what do I do here?
}).
error(function(data, status, headers, config) {
$scope.error = true;
});
How to access/parse the returned function-wrapped-JSON?
UPDATE: since Angular 1.6
You can no longer use the JSON_CALLBACK string as a placeholder for
specifying where the callback parameter value should go
You must now define the callback like so:
$http.jsonp('some/trusted/url', {jsonpCallbackParam: 'callback'})
Change/access/declare param via $http.defaults.jsonpCallbackParam, defaults to callback
Note: You must also make sure your URL is added to the trusted/whitelist:
$sceDelegateProvider.resourceUrlWhitelist
or explicitly trusted via:
$sce.trustAsResourceUrl(url)
success/error were deprecated.
The $http legacy promise methods success and error have been deprecated and will be removed in v1.6.0. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
USE:
var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts"
var trustedUrl = $sce.trustAsResourceUrl(url);
$http.jsonp(trustedUrl, {jsonpCallbackParam: 'callback'})
.then(function(data){
console.log(data.found);
});
Previous Answer: Angular 1.5.x and before
All you should have to do is change callback=jsonp_callback to callback=JSON_CALLBACK like so:
var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=JSON_CALLBACK";
And then your .success function should fire like you have it if the return was successful.
Doing it this way keeps you from having to dirty up the global space. This is documented in the AngularJS documentation here.
Updated Matt Ball's fiddle to use this method: http://jsfiddle.net/subhaze/a4Rc2/114/
Full example:
var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=JSON_CALLBACK";
$http.jsonp(url)
.success(function(data){
console.log(data.found);
});
The MOST IMPORTANT THING I didn't understand for quite awhile is that the request MUST contain "callback=JSON_CALLBACK", because AngularJS modifies the request url, substituting a unique identifier for "JSON_CALLBACK". The server response must use the value of the 'callback' parameter instead of hard coding "JSON_CALLBACK":
JSON_CALLBACK(json_response); // wrong!
Since I was writing my own PHP server script, I thought I knew what function name it wanted and didn't need to pass "callback=JSON_CALLBACK" in the request. Big mistake!
AngularJS replaces "JSON_CALLBACK" in the request with a unique function name (like "callback=angular.callbacks._0"), and the server response must return that value:
angular.callbacks._0(json_response);
This was very helpful. Angular doesn't work exactly like JQuery. It has its own jsonp() method, which indeed requires "&callback=JSON_CALLBACK" at the end of the query string. Here's an example:
var librivoxSearch = angular.module('librivoxSearch', []);
librivoxSearch.controller('librivoxSearchController', function ($scope, $http) {
$http.jsonp('http://librivox.org/api/feed/audiobooks/author/Melville?format=jsonp&callback=JSON_CALLBACK').success(function (data) {
$scope.data = data;
});
});
Then display or manipulate {{ data }} in your Angular template.
This should work just fine for you, so long as the function jsonp_callback is visible in the global scope:
function jsonp_callback(data) {
// returning from async callbacks is (generally) meaningless
console.log(data.found);
}
var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=jsonp_callback";
$http.jsonp(url);
Full demo: http://jsfiddle.net/mattball/a4Rc2/ (disclaimer: I've never written any AngularJS code before)
You still need to set callback in the params:
var params = {
'a': b,
'token_auth': TOKEN,
'callback': 'functionName'
};
$sce.trustAsResourceUrl(url);
$http.jsonp(url, {
params: params
});
Where 'functionName' is a stringified reference to globally defined function. You can define it outside of your angular script and then redefine it in your module.
For parsing do this-
$http.jsonp(url).
success(function(data, status, headers, config) {
//what do I do here?
$scope.data=data;
}).
Or you can use
`$scope.data=JSON.Stringify(data);
In Angular template you can use it as
{{data}}
for me the above solutions worked only once i added "format=jsonp" to the request parameters.
I'm using angular 1.6.4 and answer provided by subhaze didn't work for me. I modified it a bit and then it worked - you have to use value returned by $sce.trustAsResourceUrl. Full code:
var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts"
url = $sce.trustAsResourceUrl(url);
$http.jsonp(url, {jsonpCallbackParam: 'callback'})
.then(function(data){
console.log(data.found);
});