Redirect from Rails controller after Angular POST - ruby-on-rails

I have a normal Rails app (no SPA) and on one page only I'm using Angular.
At the end I'm sending a POST to the server with the form data (and it is working) and as the final step of the POST I'd like to redirect to another page.
Rails controller is like this:
def save
data = params[:data]
respond_to do |format|
format.js { render :js => "window.location.href = '/products';" }
end
end
But nothing is happening.
My Angular post is simple:
app.service('httpService', ['$http', function($http) {
this.post = function(data) {
$http({
method : 'POST',
url : '/cart/save',
data : { data: data },
headers : {'Content-Type': 'application/json'}
});
};
}]);
Calling service just like this, no promises:
this.save = function(ids) {
httpService.post(ids);
};
Any ideas? Thanks.
EDIT:
I have tried also change the mime-type to 'application/javascript', but no success:
app.service('httpService', ['$http', function($http) {
this.post = function(data) {
$http({
method : 'POST',
url : '/cart/save',
data : { data: data },
headers : {'Content-Type': 'application/javascript'}
});
};
}]);

Ok, so the problem was that the $http is sending an asynchronous request, thus the page cannot be redirected.
The solution was to send jQuery synchronous $.ajax(..., async: false);.

Related

Rails 6: AJAX data not reaching controller

I'm trying to make a pretty standard ajax call, this is my code:
// app/javascripts/packs/contacts.js
jQuery(() => {
$(".upload-contacts-button").on("click", (e) => {
e.preventDefault();
//...
$.ajax({
url: "/pre-parse-contacts",
type: "post",
data: { my_param: random_param },
success() {},
});
});
});
This is my route:
post 'pre-parse-contacts', to: 'contacts#pre_parse_contacts', as: 'pre_parse_contacts'
For some reason the data I send in the ajax request never reaches the controller, when I try to puts params in the controller action I get this result:
------- DEBUG --------
{"controller"=>"contacts", "action"=>"pre_parse_contacts"}
I'm sure the ajax call is made, even the js.erb view tries to render but I get errors due to I need the data I send in the ajax call. Why is this happening?
Sorry I found the answer to my issue, it seems I was trying to send an array of strings in the params of the ajax request, this is why it was never reaching the controller.
joining the array made the trick:
$.ajax({
url: "/pre-parse-contacts",
type: "post",
data: { my_param: random_param.join() },
success() {},
});

Ruby Devise sign up with AJAX not getting json response?

I have followed this tutorial: https://blog.andrewray.me/how-to-set-up-devise-ajax-authentication-with-rails-4-0/ And am using rails 5.1.
I have implemented the json response in the controller:
class RegistrationsController < Devise::RegistrationsController
respond_to :json
end
And when I call the ajax I only get an Html/Text response:
function createUser(callback) {
$.ajax({
type: "POST",
url: window.urls.createUser,
data: {
authenticity_token: $("meta[name=csrf-token]").attr("content"),
user: grabOrderFormUserData()
},
success: function(data) {
console.log("Data: " + data);
},
error: function (data) {
//console.log("error");
}
})
}
That call works fine, but returns the HTML page of the sign up.
The url I use is createUser: hostUrl + '/users/'
What did I miss?
And no, if I add .json to my url, it will respond with 500 error code.
I think you missed to mention dataType: "json" with your ajax call , try this
function createUser(callback) {
$.ajax({
url: window.urls.createUser,
type: "POST",
data: {`enter code here`
authenticity_token: $("meta[name=csrf-token]").attr("content"),
user: grabOrderFormUserData()
},
dataType: "json",
success: function(data) {
console.log("Data: " + data);
},
error: function (data) {
//console.log("error");
}
})
}
and also in your controller try to call this block in case if you are not getting json response,
respond_to do |format|
format.json {
render json: {.....}
}
end
thank you.

AngularJS sends nil parameters to API

I created a basic API with Ruby on Rails. Whenever I try to send data from a form in AngularJS, I get this message in the Rails Server:
Parameters: {"{\"content\":\"message\"}"=>nil}
So, it's creating null records in the DB.
This is the controller in AngularJS to send the data:
app.controller('postController', function($scope, $http) {
// create a blank object to handle form data.
$scope.message = {};
// calling submit function.
$scope.submitForm = function() {
$http({
method : 'POST',
url : 'http://localhost:3000/api/v1/messages',
data : $scope.message, //forms user object
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function(data) { ... }
});
};
});
You need to serialize the data when you send as x-www-form-urlencoded
Example copied from docs
.controller(function($http, $httpParamSerializerJQLike) {
//...
$http({
url: myUrl,
method: 'POST',
data: $httpParamSerializerJQLike(myData),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
});
Or use the defaults of $http which sends JSON in request body as application/json:
$http.post(myurl, data).then(...;
change this line:
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
to:
headers : {'Content-Type': 'application/json'}
Also encode to Json if it isnt like this:
data : angular.toJson($scope.message), //forms user object
This way you will send the correct JSON formatted data to API, make sure your API accepts Json encoded data just in case.

Can not post json data using angularjs to MVC controller

I simply want to post the data my data which is JSON object but I can not. the post via firebug shows that I am actually posting json data to server d, but when debugging the controller my d is null.
$scope.update = function() {
$http({
method: "POST",
url: 'EditData',
data: {d: $scope.myData},
}).success(function() {
alert(data.msg);
});
};
I did try to JSON.parse myData that didn't work either.
Here is my controller:
public JsonResult EditData(string d)
I am not sure what I am doing right here. probably something silly. :(
This worked for me. JSON.stringify();
$scope.update = function() {
$http({
method: "POST",
url: 'EditData',
data: {d: JSON.stringify($scope.myData)},
}).success(function() {
alert(data.msg);
});
};
try:
$scope.update = function() {
$http({
method: "POST",
url: 'EditData',
data: $scope.myData,
}).success(function() {
alert(data.msg);
});
};

Read cross domain JSON response

<script>
$.ajaxSetup( {contentType: 'application/json'} );
function submit_data(f){
alert('submitting')
var data_string = $(f).serialize();
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?jsonpcallback=?"+data_string,
dataType: "jsonp",
type : 'post',
processData: false,
crossDomain: true,
contentType: "application/json",
jsonp: false,
jsonpcallback: result()
});
}
function result(){
alert('back in')
alert(data)
}
function jsonp1300279694167(){
alert('dhoom')
}
</script>
I have script above querying across domain and posting data within a form.
Everything seems to work fine. JSON response can be seen in the firebug console. I want to process the response and display status messages accordingly to the user. How should I achieve it?
UPDATE
I have tried as suggested by T.J. Crowder but have no luck yet. The modified code is as below
function submit_data(f){
alert('submitting')
var data_string = $(f).serialize();
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?"+data_string,
dataType: "jsonp",
crossDomain: true,
success: handleSuccess()
});
}
function handleSuccess(data) {
alert("Call completed successfully");
alert(data);
}
This does not accesses data and alerts undefined. If I try to pass it from success: handleSuccess() it errors and redirects with a http request.
I am getting response from a Ruby on Rails application. Here is the method I am hitting
def create
errors = ContactUsForm.validate_fields(params)
logger.info errors.inspect
if errors.blank?
respond_to do |format|
format.json {render :json => {:status => 'success'}.to_json}
end
else
respond_to do |format|
format.json {render :json => {:status => 'failure', :errors => errors}.to_json}
end
end
end
Is there any thing that I need to configure in my rails app
You're close. You just use the success callback as usual (see the ajax docs), not a special one:
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?jsonpcallback=?"+data_string,
dataType: "jsonp",
type : 'post',
processData: false,
crossDomain: true,
contentType: "application/json",
jsonp: false,
success: function(data) {
// Use data here
}
});
Also, your code:
jsonpresponse: result()
...would call the result function and then use its return value for the jsonpresponse property of the ajax call. If you want to use a separate function, that's fine, but you don't include the (), so:
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?jsonpcallback=?"+data_string,
dataType: "jsonp",
type : 'post',
processData: false,
crossDomain: true,
contentType: "application/json",
jsonp: false,
success: result
});
function result(data) {
// use `data` here
}
Also, I'm pretty sure you don't need/want the jsonp parameter if you use success, so:
$.ajax({
url: "http://localhost:3000/application/1/contact_us.json?jsonpcallback=?"+data_string,
dataType: "jsonp",
type : 'post',
processData: false,
crossDomain: true,
contentType: "application/json",
success: result
});
function result(data) {
// use `data` here
}
Finally: Are you sure you want to set contentType? That relates to the content being sent to the server, not the content being received from it. If you're really posting JSON-encoded data to the server, great, you're fine; but it looks like you're using jQuery's serialize function, which will not produce JSON (it produces a URL-encoded data string). So you probably want to remove contentType as well, both from the call and from the ajaxSetup call.
I hope if you can try jQuery-JSONP
jQuery-JSONP How To
[Example]
$.getJSON('server-url/Handler.ashx/?Callback=DocumentReadStatus',
{
userID: vuserID,
documentID: vdocumentID
},
function(result) {
if (result.readStatus == '1') {
alert("ACCEPTED");
}
else if (result.readStatus == '0') {
alert("NOT ACCEPTED");
}
else {
alert(result.readStatus);
}
});
I tried many tutorials including the answers above but had no luck. So I implemented it something like below
Form
<form action="" onsubmit="submit_data(this, '1'); return false;">
// some form fields
</form>
Submit function for form
<script>
function submit_data(f, app_id){
var data_string = $(f).serialize();
$.ajax({
url: "http://www.example.com/"+app_id+"/contact_us.js?"+data_string,
dataType: "jsonp",
crossDomain: true,
});
}
function show_errors(jsonOb)
{
$("span.error").remove();
$.each(jsonOb, function(key,val){
$("#contact_us_form_"+key).after("<span class=error>"+val+"</span>")
});
}
</script>
In my controller
def create
#application = Application.find params[:application_code]
#errors = ContactUsForm.validate_fields(params, #application)
#application.save_contact_us_form(params[:contact_us_form]) if #errors.blank?
respond_to do |format|
format.js #{render :json => {:status => 'success'}.to_json}
end
end
And finally in create.js.erb
<% if #errors.blank? %>
window.location = "<%= #application.redirect_url %>"
<% else %>
var errors = replaceAll('<%= escape_javascript(#errors.to_json)%>', """, "'")
var errors_json = eval('(' + errors + ')')
show_errors(errors_json);
function replaceAll(txt, replace, with_this) {
return txt.replace(new RegExp(replace, 'g'),with_this);
}
<% end %>
This way I called submit_form on form submit and called show_errors javascript function from server it self. And it works..
But still I would like to have comments if this is a worst solution?

Resources