steel
steel

Reputation: 12520

Rails, JQuery, Ajax = Ajax params missing variable

I am trying to access the JQuery Ajax call's data in my controller. Params does not hold this value, though it is supposed to. When I look at the request in Chrome, under Form Data I see the parameter's correct key-value pair, so I know JQuery is sending it.

How can I access this key-value pair that I am sending to the controller from the Ajax request?

#config/routes.rb
post 'projects/get_sum' => 'projects#get_sum', as: :get_sum

#from $ rake:routes
get_sum POST   /projects/get_sum(.:format)  projects#get_sum

#index.html.erb
<%= link_to 'Get sum', get_sum_path, id: "get_sum", method: :post , remote: true %>
<input id="input_val"></input>

#get_sum.js.erb
var $val = $('#input_val').val();
$.ajax({
    type: 'POST',
    url: 'projects/get_sum',
    data: { my_val: $val },
    success: function (data, textStatus, jqXHR) {
        console.log('Val is ' + $val); #returns correct input value
        console.log('Data is ' + data); #returns get_sum.html.erb
        $('#get_sum').hide().after("<%= 'sum: ' + @sum.to_s + '. Params: ' + params.inspect %>");
    },
    error: function() {
        console.log("Request error.");
    }
});

#projects_controller.rb
def get_sum
  @sum = Project.sum(:cost)
  @params = params # returns controller and action only
  @val = params[:my_val] #returns nil
end

#and in the rendered view, the following results:
sum: 95. Params: {"controller"=>"projects", "action"=>"get_sum"}

UPDATE

Well, it's becoming clear that this method is Doing It Wrong. My issue here is at least that I am calling the controller method first, which then triggers the .js.erb template, which then calls the HTML response of the same controller method. Which is why the parameters aren't being passed.

By using a link_to_function call instead, that triggers a JQuery Ajax call to the controller method that then loads the .js.erb template, I've made this scenario work. It feels clunky, and I'd still love to hear about a best practice for passing client-side variables to a server-side calculation, then ansynchronously rendering the result, without using forms.

Upvotes: 0

Views: 869

Answers (1)

PatoBeltran
PatoBeltran

Reputation: 133

When you use the remote: true in rails you don´t need to take care of the ajax call, because rails will do it for you. So it calls the controller, but instead of loading an html, it will load the myMethod.js.erbversion of it.

So what you need to do, is change the HTML in your index.html.erb to use a form:

<%= form_tag get_sum_path, method: :post, id: "get_sum", remote: true do %>
    <%= label_tag :input_value, "Value:" %>
    <%= text_field_tag :input_value %>
    <%= submit_tag "Get sum" %>
<% end %>
<div id="results"></div>

Then if you print the params in the controller you will see the "input_value" added to it. So if you modify your get_sum.js.erb to have this:

$('#get_sum').hide();
$('#results').text("<%= @value %>");

And that should take care of the ajax request. Here is a link that might be helpful, and there´s also a RailsCast for this. http://www.tutorialspoint.com/ruby-on-rails/rails-and-ajax.htm

Also, I encourage you to use the rails debugger gem when trying to check for this things. https://github.com/cldwalker/debugger

Upvotes: 1

Related Questions