angular http post adds extra params to the request - javascript

I have the following in a directive:
scope.progressCourse = ->
req_data =
course_id: scope.course.id
success: true
$http.post(
"<%= Rails.application.routes.url_helpers.progress_course_path %>",
req_data
).then (succesful_resp) ->
scope.course = succesful_resp.data.data
scope.init_from_course_object()
, (error_resp) ->
show_error(error_resp)
And, server side, I'd expect to receive the course_id and success params. However, I receive something extra:
Parameters: {"course_id"=>1, "success"=>true, "training"=>{"course_id"=>1, "success"=>true}}
The request is addressed to a controller called TrainingController. I'm running Rails 3.2.13, with angular 1.2.10. Could someone explain why the extra hash appears {"training"=>{"course_id"=>1, "success"=>true}}
UPDATE:
If I add this:
$httpProvider.defaults.transformRequest = (data) ->
if data?
return $.param(data)
return data
and I change the post to:
$http(
method: "POST"
url: "<%= Rails.application.routes.url_helpers.progress_course_path %>",
data: req_data,
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
).then (succesful_resp) ->
Then I only get the 2 params I need. Can someone explain why this behaviour?

Rails has a lot of inbuilt functionality to make dealing with external APIs easier. In this case it has a params_wrapper that will manipulate parameters passed in in a request, nesting them in the hash that it assumes you want.
For example, if you are submitting {name: 'foo', age: 12} to a UsersController, it will assume that they should be wrapped in a nested user key and will do this for you transparently.
Documentation for this wrapper is here:
http://api.rubyonrails.org/v3.2.13/classes/ActionController/ParamsWrapper.html
And the code is here:
https://github.com/rails/rails/blob/v3.2.13/actionpack/lib/action_controller/metal/params_wrapper.rb
If you don't want this functionality, you can disable it by commenting out the wrap_parameters format: [:json] line in /config/initializers/wrap_parameters.rb.

Related

AJAX not resolving url correctly

I have an HTML form that I want to submit to a flask endpoint, /add_int. When the form is submitted I intercept it with Jquery and submit the form to the endpoint using AJAX as follows:
var form = $( this ).serialize()
$.post({
url: "{{ url_for('add_int') }}",
data: JSON.stringify(form),
contentType: 'application/json;charset=UTF-8',
success: function(resp) {
console.log(resp);
}
});
The endpoint looks like this:
#app.route('/add_int', methods=['GET', 'POST'])
#login_required
def add_int():
# do stuff
return jsonify(status="success!")
My issue is that I never get to the endpoint.
When I examine my console I see
POST http://127.0.0.1:5000/[object%20Object] 404 (NOT FOUND)
instead of
POST http://127.0.0.1:5000/add_int
as I'd expect.
Note that if I set
url: '/add_int',
I run into the same problem.
I've found cases that use almost identical code that don't mention this problem:
e.g. how can I use data posted from ajax in flask?
My guess, is that my url is being resolved as a String object rather than a url, but I can't figure out why it's happening, and how to fix it.
What's going on?
You should remove the call to JSON.stringify, you can pass a serialized form directly as POST data and JSON.stringify is turning your object into [Object object].
url: '/add_int', isn't working because (it appears that) your frontend is running on a different port than the backend, so it will be rejected as a "cross domain" request. Have you inspected the value that "{{ url_for('add_int') }}" is returning?
Try not specifying the hash keys explicitly. http://api.jquery.com/jquery.post/
$.post("{{ url_for('add_int') }}",
JSON.stringify(form),
function(resp) {
console.log(resp);
},
'application/json;charset=UTF-8'
);

With AngularJS, I don't want to set the global $http.defaults.headers.common. Can I send my custom header with each $resource call?

I'm calling a back-end server that I cannot control. Currently it's using jQuery ajax like this:
return $.ajax({
type: "POST",
url: "/api/cases/store",
contentType: "application/json",
data: JSON.stringify(parameters),
headers: { "Authorization": cred } : {}
}) // ... etc.
I want to convert it to use the $resource service, and got it working doing this
$http.defaults.headers.common['Authorization'] = cred;
return $resource('/api/cases/store').save();
The only problem is that I'm having to set the global $http service defaults with the auth credentials.
I am seeing that you're supposed to be able to pass in custom headers with the $http call, and now with $resource calls, but I can't find any examples of how to do it in my case (with a POST).
I also can't find anything on this in the AngularJS documentation. How do you guys figure this stuff out? The docs are so bad!
Instead of this:
$http.defaults.headers.common['Authorization'] = cred;
return $resource('/api/cases/store').save();
Do this:
return $resource('/api/cases/store', {}, {
save: {
method: 'POST',
headers: { 'Authorization': cred }
}
}).save();
Note that you have to use 'save' as the action, the first key in the third parameter. Can't test it, so let me know if it works.
And I agree. The documentation doesn't talk about it. Take a look at the DEFAULT_ACTIONS list in the $resource source-code in angular-resource.js
The $resource documentation does cover it, though its certainly awkward to read. You have to make a custom action for it, and all the parameters you can pass to the config are NOT listed on the $resource page. You'll want to check out the $http docs page for the possibilities for the config object.
$resource() takes 3 arguments: the URL, the default parameters object, and the actions object. Actions map method names to $http configs, basically.
You want to make a custom action, something like:
var MyResource = $resource('/myendpoint/', {}, { 'post': { method: 'POST', headers: {"Authorization" : cred}}); // and any other $http options you might want
Those actions get turned into methods on the MyResource object, so you could name the action something more semantic than just "post" if you wanted (the examples on the docs page set up a "charge" action for a credit card resource, for instance).
The documentation for $http is pretty solid, as is most of the other documentation on their site.
And you can absolutely define your auth headers on each individual AJAX calls.
try something like this:
$http({
method: 'POST',
url: 'serverUrl',
data: parameters,
headers: { Authorization: cred }
});

Implementing Ajax calls for a REST API

I have built a back end REST API using Slim Framework and followed the REST format as close as I could.
Once I started working on the Front End I realized that AJAX works great with parameters and not paths
(param file?param=value , paths file/object/method/id)
I am planning on out sourcing or building an APP with xamarin or other 3rd party to consume the API, but for now a Alpha test will be done with HTML and AJAX calls.
Example call example.com/user/test or example.com/advertiser/2
So how do I query the API, do I just concat URL strings?
.ajax({ ... url : 'example.com/user/'+user ...});
EDIT:
Yes I know AJAX is domain sensitive, and Yes I am using verbs GET,POST,PUT and DELETE.
What is going on is the following :
When passing variables in an AJAX request they get appended as
PARAMS example.com/users/?user=Pogrindis
in an REST API at least as far as I read it goes
example.com/users/Pogrindis that's a path
reference parse.com/docs/rest#general-quick
Ajax has set definitions how to do this : https://api.jquery.com/jQuery.ajax/
Your passing user as a param, over get // post method and you are specifying what you expect back.
If i understood the question correctly you are looking at something like:
$.ajax({ url: 'example.com/user/',
data: {user: user}, // Params being sent
type: 'post',// Or get
dataType: 'json' // Or whatever you have
success: function(output) {
//.. do what you like
}
});
There should be no problem.
The data being passed into it will append to the url for GET-requests, i think thats what you mean.. Your data object can be constructed before sending via ajax.
There needs to be a route to query for data. Unless you define some flag on the server to point to the correct location, then you could pass through a route param but you need to have a pointer URL. Building the route can be painful, and subsequent calls will be more challenging but you can do it ?
After doing some research here is a solution used
FRONT END
$.ajax({
url: '/user/'+getid,
data: getdatastring,
type: 'GET',
datatype: 'json',
cache: false,
success: function(data) {
data = JSON.parse(data);
}
});
BACK END
SLIM PHP FRAMEWORK
$app->put('/user/:id', function($id) use ($app,$_pdo) {
$obj = new dbModel($_pdo);
$objApi = new Controller($obj);
$arrParams = json_decode($app->request()->getBody(),true);
$arrUser= $objApi->getUserInfo($id,$arrParams);
print json_encode($arrUser);
});

Data is not saved properly in MogoDB from Angular js through Node.js

I am building an application with Angular.js,Node.js and MongoDB.
I am sending a set of data to MongoDB as below.
$http({
method: 'POST',
url:'http://localhost:2000/postsharedata', data:({event:$scope.event,date:$scope.eventdate,expenselist:$scope.expenses,expense:$scope.totalAmount,sharelist:$scope.sharelists,shareno:$scope.share()}),
}).success(function(data) {
console.log(data);
});
expenselist while sending to MongoDB is as follows:
[Object { text="a", done=true,$$hashKey="00I",$oldValue="5000",$value="5000"}]
But in mongoDb,data is like [ { "text" : "a", "done" : true }]
Why $oldValue and $value are not getting stored?
Please Advice
If you use the $http post service to submit your data to your server, angular converts your data and strips all properties that are prefixed with at least one $ character. This is documented in the toJson function (http://docs.angularjs.org/api/angular.toJson).
If you want to submit your data regardless the leading $ character you have to change the way how angular transforms your data before the submit happens. This can easily be done by using the transformRequest config parameter:
$http({
method: 'POST',
url:'http://localhost:2000/postsharedata',
data:(... your data ...),
transformRequest: function(data){return data}
})
More information in the $http service documentation.

JQuery AJAX PUT, not working

I'm sending a JQuery AJAX call as follows, to update a record in an ActiveRecord DB:
var url_out = '/users/' + args.item.id;
$.ajax({
url: url_out,
type: 'POST',
method: 'PUT',
data: args.item,
success: function(dat) {
alert("did it");
}
In Users controller, I have this:
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
So I need to pass the data that's in args.item, instead, as params[:user]. Can one pass named parameters using the AJAX call?
I might be wrong, but I know that Rails actually is simulating the http verbs by adding a hidden parameter _method with value "PUT" and the actual request is a POST (due to some browsers not supporting all the verbs")
SO, you can try to do a post and add a parameter _method: "PUT"
I'd like to thank #Dom and #Eduard for the help. It turns out I needed to do something like this:
x_out = {};
x_out["first_name"] = args.item.first_name;
x_send = {};
x_send["user"] = x_out;
and that lets me pass the named parameter to the update method in the controller.

Categories

Resources