AngularJS: POST parameters in array notation - angularjs

My angular.js app posts the following JSON to my backend API:
{"pickupAddress":
{"state":"d","country":"d","city":"d","zipCode":"d","street":"d"},
...}`
Instead of that my backend API required to receive not pickupAddress.state, but pickupAddress[state].
I tried to change the ng-model in my view (to myObject.pickupAddress['country']) but this produces some strange errors.
I want something which results in this (using raw html):
<input type="text" name="pickupAddress[state]" />

The way Angular serializes POST data if you provide an object source is in fact uses not notation your service expects. If instead you use jQuery $.param method to serialize object into param-string and post this string, it should work:
var data = $.param({
"pickupAddress": {
"state": "d",
"country": "d",
"city": "d",
"zipCode": "d",
"street": "d"
}
});
$http.post('test', data, {
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
Above will post data as
pickupAddress[state]:d
pickupAddress[country]:d
pickupAddress[city]:d
pickupAddress[zipCode]:d
pickupAddress[street]:d
Check this discussion in Angular issue page.

Related

Angularjs $resource query method working but get method not working

Here is my factory method:
.factory('lettersFactory', ['$resource', function ($resource) {
var url = "";
if(ionic.Platform.isAndroid()){
url = "/android_asset/www/";
}
return $resource(url + 'data/letters.json');
}])
And here is the controller:
.controller('LettersCtrl', ['$scope','lettersFactory', '$stateParams', '$state', '$ionicPopover', function($scope, lettersFactory, $stateParams, $state, $ionicPopover) {
$scope.letters = lettersFactory.query();
$scope.letter = lettersFactory.get({number:parseInt($stateParams.letterId, 10)});
}])
And here is the Error message:
Error in resource configuration for action object. Expected response to contain an array but got an GET (Request: data/letters.json {4})
And my letter.json is an array like this:
[
{"number":1,
"title": "title",
"content": "content"},
{"number":1,
"title": "title",
"content": "content"}
]
Thanks
If the response should not be an array then you need set the isArray as false in query property.
'query': {method: 'GET', isArray: false }
Refer to the document.https://docs.angularjs.org/api/ngResource/service/$resource
Or you can pass the json as array from the controller.
The default method set for $resource contains these actions1:
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
In your case the get method is failing because the data from the XHR is an array and the method expects an object.
The query method succeeds because the data from the XHR is an array and the method expects an array.
Use the get method for object data; use the query method for array data.
Update
how do you think I can use the query method in this situation to get a particular object from the array data?
One approach is to use the $promise property of the returned resource object:
$scope.array = lettersFactory.query();
$scope.array.$promise.then(function(resourceArray) {
$scope.item = resourceArray[0];
});
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.
The Resource instances and collections have additional properties:
$promise: the promise of the original server interaction that created this instance or collection.
On success, the promise is resolved with the same resource instance or collection object, updated with data from server.
On failure, the promise is rejected with the http response object, without the resource property.
For more information, see AngularJS $resource API Reference

AngularJS Chaining $http calls

I am still quite new to AngularJS and struggling to figure the following out.
I have quite a few web-services that I need to use, quite a few of them relies on the data from another to successfully make the next call.
For example, the first web-service will retrieve a list of Profiles.
ip.controller("ProfilesCtrl", function($scope, $http) {
$http.post("Profile_List.asp").success(function(data) {
$scope.profiles = data;
}).error(function() {
alert("An unexpoected error ocurred while loading profiles!");
});
});
Profiles returns a JSON object.
Data returned:
{
"Success": true,
"ErrorMessage": "",
"Objects": [{
"GUID": "208FF69D-A4EB-4760-B2ED-414C900F4AAC",
"Name": "John Doe",
"Status": false
}, {
"GUID": "BC5C53FD-5CA7-4DBE-8594-D26AD88B758B",
"Name": "Jane Doe",
"Status": true
}, {
"GUID": "2FCD677B-DA36-4014-823A-9BDD1A72AD66",
"Name": "Anonymous",
"Status": true
}]
}
Ok, so after I have made the initial call, I need to send the GUID of each Profile Object to another web-service. This service will use the GUID to determine the ID of that specific Profile.
The data from the second web-service will only return the ID for the GUID of the first call.
How can I chain these $http calls? Would it be better to create a new json object and use data from there?
I have done this before using ajax.
*Another question regarding my controller code, is this fine like this or would it be better to maybe do the $http calls as a Service, Provider or Factory? How can I go about doing this?
Any help/links with getting the above to AngularJS code would be appreciated.
Please ask if anything is unclear.
Simply call execute the next call in your "success" handler.
$http.post("Profile_List.asp").success(function(data) {
$scope.profiles = data;
//first call succeeded, and we have the data. call method 2
executeStep2($scope.profiles);
})
function executeStep2(profiles)
{
$http.post("second_method") // etc. (you can just send profiles as post data here)
}

Using locale in the $resource URL

My AngularJS application is getting server data from a rails JSON API and the API routes are localized, for example:
/:locale/api/categories/
I am trying to define a $resource that would enable the localization. So far, I've been unsuccessful (see the approaches I've tried below).
First attempt
$resource('/:localeId/api/categories/:categoryId', {
localeId: $locale.id,
categoryId: "#id",
format: 'json'
})
This does not work. The localeId is only evaluated once, when the $resource is created.
Second attempt
$resource('/:localeId/api/categories/:categoryId', {
localeId: "$locale.id",
categoryId: "#id",
format: 'json'
})
This does not work either, the generated URL is /$locale.id/api/categories/.
Third attempt
$resource('/:localeId/api/categories/:categoryId', {
localeId: "#localeId",
categoryId: "#id",
format: 'json'
})
This works but obliges me to define localeId everytime I use my $resource.
Is there a better way to automatically use $locale.id inside my $resource URL?
Just provide a function that returns your value (see documentation):
$resource('/:localeId/...', {
localeId: function () {
return $locale.id;
},
// ...
})

Angularjs JSONP not working

I might be missing something here but I can't make this JSONP request work, here is the code:
var url = 'http://' + server + '?callback=JSON_CALLBACK';
$http.jsonp(url)
.success(function(data){
console.log('success');
})
.error(function () {
console.log('error')
});
The request fires ok and I am getting the response (with header Content-Type:application/json) in this format:
[{"id": "1", "name": "John Doe"},
{"id": "2", "name": "Lorem ipsum"},
{"id": "3", "name": "Lorem ipsum"}]
Can you see anything wrong? Maybe the format I should return from the server is not right?
Angular fires the error callback without any error message besides the one I set ('error').
#TheHippo is correct the data should not just be a plain json response. Here is a working example of a JSONP request against a youtube endpoint in AngularJS.
A couple of things to note in this example:
Angular's $http.jsonp converts the request querystring parameter from callback=JSON_CALLBACK to callback=angular.callbacks._0.
When calling the youtube endpoint I needed to specify to the service that this is a JSONP request by using alt=json-in-script instead of alt=json in the querystring. This was found in their documentation.
Compare the results of this url to this one to see the difference between JSON and JSONP response in your browser.
Take a look at the Chrome Network Panel in Developer Tools to help compare and troubleshoot with your request/response.
I know this example is very specific but hopefully it helps!
JSONP requires you do wrap your data into a JavaScript function call. So technically you return a JavaScript file and not a Json file.
The data returned from server should similar to this:
// the name should match the one you add to the url
JSON_CALLBACK([
{"id": "1", "name": "John Doe"},
{"id": "2", "name": "Lorem ipsum"},
{"id": "3", "name": "Lorem ipsum"}
]);
Edit: If some one else stumbles across problems with angular's JSONP please also read this answer to this question, it contains usefull informations about how angular handles the actual callback function.
If the response data is "pure" JSON, we can just handle it with angular's $http.get.
$http.get(url).
then(function(response) {
// this callback will be called asynchronously
// when the response is available
$scope.responseArray = response.data;
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Refer to the example on w3schools

How to create Backbone Collection from a JSON API call that returns root parameters as well as array

Backbone.js noob here.
I want to create a collection, from a JSON API external to my application. Specifically, the api from Stackoverflow. I know I should set the url parameter from a collection like this:
App.Collections.Users = Backbone.Collection.extend({
model: User,
url: "http://api.stackoverflow.com/1.1/users/800271;562692?jsonp=?&key=blahblah"
});
The problem is that the JSON API returns something like:
{
"total": 2,
"users": [
{
"user_id": 800271,
},
{
"user_id": 800272,
}
]
}
}
How do I ignore the "total" attribute?
If this is the only collection in your app to work with such api, all you have to do is to override parse method for it:
App.Collections.Users = Backbone.Collection.extend({
// ...
parse: function(resp, xhr) {
return resp.users
}
})
If you also have to save your models, maybe you will need to override Backbone.sync. Don't hesitate to read backbone's source: it's thoroughly annotated and easy to follow.

Resources