how to send remote form params - ruby-on-rails

I have a form which is using several input fields being ajaxified with remote: true and custom controller actions. This way UJS driver sends only given form input as params. What I want to accomplish is an ajaxified input field which will send value of a field outside of it's "scope" as params. What do you suggest?

Let me explain the whole flow of the ajax-rails and remote=> true and you can do this with that following way and you can get all the params in your method.
first when you used the remote=> true then the form will submit or call the action which you have define in form like here is an example:
<%= form_tag({:controller => 'my', :action => 'my_data'},:id => 'filter_form', :remote => true) do %>
#code here
<%= submit_tag 'save', :name => 'commit'%>
<%end%>
now above code will go to my_data action in my controller,
here you can define the respone type with
def my_data
#actions on data here
respond_to do |format|
format.js
end
now you have to made a .js file with named as action name....
my_data.js.erb
here the whole affect of form you can write and update document element through jquery and javascript.
For every input you just assign a class and write a method that call when the input box will change.One more thing that when you wants to do in a single method the every input have a unique ID, send that also in params and do task what ever you wants to do.

Rails' JQuery UJS is just a dependency which Rails uses to call ajax requests on your behalf. This means your question is not particularly to do with JQuery UJS, but with how to handle it with ajax overall
You'll typically handle any extra data by appending it to the Ajax request:
<%= link_to "Link", new_post_path(params: "here"), remote: true %>
If you want to create an "ajaxified" field, you'll probably have to use a manual ajax call to capture the change event, allowing you to send the data to your event:
#app/assets/javascripts/application.js
$('input[name="element"]').on("change", function(){
$.ajax({
url: "url",
data: $(this).serialize()
});
});
Then, as mentioned by #baharat Soni, you'll be able to handle the request on the server using respond_to

Related

Rails with jQuery + AJAX fundamentals

I've been given a task to do a simple Task Manager on Ruby On Rails. It's pretty simple for me but there is one issue. Everything has to be "ajaxified" and data should be passed around in JSON.
How I do this right now.
On index.html.erb
I'm creating a simple form with these parameters:
<%= form_for(Task.new, remote: true, :html => {:'data-type' => 'json'}) do |f| %>
In TasksController:
class TasksController < ApplicationController
respond_to :json
def create
#project = Project.find(params[:task][:project_id])
if #task = #project.tasks.create!(name: params[:task][:name], description: params[:task][:description])
respond_with(#task)
else
flash[:error] = 'error'
end
and inside on index.htm.erb I have:
$(document).ready(function(){
$("#new_task").bind('ajax:success', function(evt, data, status, xhr){
var row = ('<tr id="task.id"><td>'+data.name+'</td>'+'<td>'+data.description+'</td>'+'<td>'+data.state+'</td>'+'<td><%= link_to "delete task", task_path(task.id), :method => "delete", remote:true, data: { confirm: "Are you sure?" } %></td></tr>');
$(row).insertAfter("#tasks_table tr:first");
slicer($("#total"));
slicer($("#active"));
}); });
$("#new_task").bind("ajax:beforeSend", function(event,xhr,status){
$(this)[0].reset();
});
And now I'd like to give some explanation about how this might work(my personal thoughts)
by specyfing remote: true, I'm telling the form to submit data in input on server via Unobtrusive Javascript, rails 3 feature. It sends an usual hash in my example this is params[:task][:name] etc, but it expects to get back JSON because I did set :html => {:'data-type' => 'json'}) (is this correct syntax?). Now in my TasksController class I have the respond_to :json, it means that controller WILL answer those requests, where data-type json is specified, with json, because respond_with is smart enough to do to_json on object you are doing respond_with.
Am I right in all those assumptions?
So the question is if we can use js.erb and json.erb(yes?) do you need to return the json at all ?
Maybe going a step back helps.
With AJAX form, the submit event goes through JavaScript first, and does not trigger the browser to invoke a POST '/data.json'.
If you look at the HTML that is generated by Rails with the remote: true option, you probably see a "onsubmit()" or similar callback. It is also the JavaScript, that processes a 'success' or 'error' event. I like the jQuery documentation for this: http://api.jquery.com/jQuery.ajax/
Your question is also somewhat opinionated, because JavaScript libraries such as Backbone.js, Ember.js or Angular, allow to fine-tune the process chain of a form submit even further.

Pass js variable to server code

I have a form with 2 inputs and button. An user put feed url in the first input and press the button:
<%= link_to "get name", { :controller => 'Feeds', :action => "get_title" },
:remote => true, :class=>'btn btn-mini' %>
Here is controller method
def get_title
respond_to do | format |
format.js {render :layout => false}
end
end
And here is a get_title.js.erb:
var url = $( "#feed_url" ).val();
console.log(url);
$( "#feed_name" ).val("<%= #proxy.title(url) %>");
I get value of the first input and want to pass it as parameter to Ruby class. But in this case I get the error:
ActionView::Template::Error (undefined local variable or method `url' for #<#<Class:0x41ec170>:0x41ef968>):
1: var url = $( "#feed_url" ).val();
2: console.log(url);
3: $( "#feed_name" ).val("<%= #proxy.title(url) %>");
Rails this that 'url' is a Ruby variable, but not JS one.
How can I pass JS variable to Ruby code ?
Thanks in advance.
Remember that any ERB (ruby) code is executed server side, while Javascript is, of course, rendered client side. As a result, your line <%= #proxy.title(url) %> is rendered WAY before that url value is ever evaluated. The solution to your situation is more along the lines of passing data to Rails, and rendering the response. Three things to facilitate this (bearing in mind that this is only one approach, and I'm sure there are plenty of others, and possibly better ways of doing this):
1- Your link_to won't post the user-input URL value because it is not POSTing the form. Instead, change the surrounding form to use :remote=true, and use a typical form.submit button rather than this link. Your form with the URL value will be submitted (and it will be asynchronous).
2- In your controller, render your title like you were trying to do, doing something along these lines:
def get_title
render :text=>#proxy.title(params[:url])
end
3- Bind to the ajax:success event, something along these lines:
$("form#myForm").bind("ajax:success", function(event, data, status, xhr){
$( "#feed_name" ).val(data) // data, in this case, is the rendered `#proxy.title(url)` we did in step 2.
})
Hope that makes sense. Let me know if it does not.

Where to store view parameters in an AJAX session?

In a non-AJAX web app, the URL would contain my view parameters (e.g. mysite?page=2&sort=name). In an AJAX app, where do I store the same info? In the Session object?
I'm assuming you want to know how to pass additional params with an AJAX call. This really depends on how you're formulating the AJAX call.
If you're using the built-in Rails helpers, you can pass additional params inside the url_for helper. For example, lets say that you have a products route and you want to AJAX load a list of all products. The link_to helper might look something like this (Rails 3.2)
link_to "All Products", products_path(:page => 2, :sort => "name"), :remote => true
If on the other hand you're using a JavaScript framework like jQuery, you can pass additional params using the data option. For example
$.ajax({
url: "/products",
data: {
page: 2,
sort: "name"
},
success: function(data) {
// handle success
},
failure: function(data) {
// handle failure
}
});
Storing this data (page, sort, etc.) can be done multiple ways also. The easiest way would be to store this data inside a JavaScript variable.
window.page = 2;
window.sort = "name";
Another solution is to store this information in the data attribute of a particular DOM element on the page. For example, if you have a <div id='products'> that contains a list of the paginated, sorted products, you could store the information like this (jQuery)
$("#products").data("page", 2);
$("#products").data("sort", "name");
Generally speaking, you don't structure you're requests differently for AJAX in Rails. You'll just add the :remote => true attribute to your link or form, then make the controller action respond_to js
respond_to do |format|
format.js
end
And then put your_action.js.erb in your views and write javascript that updates the dom in the appropriate way.

Rails controller not rendering correct view when form is force-submitted by Javascript

I'm using Rails with jQuery, and I'm working on a page for a simple site that prints each record to a table. The only editable field for each record is a checkbox. My goal is that every time a checkbox is changed, an ajax request updates that boolean attribute for the record (i.e., no submit button).
My view code:
<td>
<% form_remote_tag :url => admin_update_path, :html => { :id => "form#{lead.id}" } do %>
<%= hidden_field :lead, :id, :value => lead.id %>
<%= check_box :lead, :contacted, :id => "checkbox"+lead.id.to_s, :checked => lead.contacted, :onchange => "$('#form#{lead.id}').submit();" %>
<% end %>
</td>
In my routes.rb, admin_update_path is defined by
map.admin_update 'update', :controller => "admin", :action => "update", :method => :post
I also have an RJS template to render back an update. The contents of this file is currently just for testing (I just wanted to see if it worked, this will not be the ultimate functionality on a successful save)...
page << "$('#checkbox#{#lead.id}').hide();"
When clicked, the ajax request is successfully sent, with the correct params, and the action on the controller can retrieve the record and update it just fine. The problem is that it doesn't send back the JS; it changes the page in the browser and renders the generated Javascript as plain text rather than executing it in-place.
Rails does some behind-the-scenes stuff to figure out if the incoming request is an ajax call, and I can't figure out why it's interpreting the incoming request as a regular web request as opposed to an ajax request.
I may be missing something extremely simple here, but I've kind-of burned myself out looking so I thought I'd ask for another pair of eyes. Thanks in advance for any info!
In your controller you need to specify the proper response. Since you didn't post the controller I'll just try to fill in the blanks.
def update
# Update something
respond_to do |format|
format.js # this renders your rjs file
end
end
Specifying the format tells the rails app to interpret the javascript instead of just sending it back as text.
The other option instead of using rjs is to do an inline rjs block like this:
render :update do |page|
page.replace_html 'user_list', :partial => 'user', :collection => #users
page.visual_effect :highlight, 'user_list'
end
Only use the inline rjs if you will be doing minimal changes to the interface that can be put into one or two lines. Anything more should be in it's own rjs file.
This question is related to this one, but the answer varies slightly. I had to create a new way to submit the form, since the default jQuery submit() method does not submit as a 'script' and certainly does not fire the code that Rails generates in the onsubmit="..." handler via the form_remote_tag helper.
The solution was to create a new function as the linked answer suggests, but the contents are slightly different:
jQuery.fn.submitWithAjax = function() {
jQuery.ajax({data:jQuery.param(jQuery(this).serializeArray()) + '&authenticity_token=' + encodeURIComponent('<%= form_authenticity_token %>'), dataType:'script', type:'post', url:'/update'});
return false;
};
This is brittle right now-- notice that I insert rails' form_authenticity_token into the Javascript, but really the method (post) and the url (/update) should also be generated rather than hardcoded.
Things are working A-OK now.

how can I hide params I transmit to a method (like form_for seems to do)?

I've been searching for hours now and haven't found anything that helps.
What I want to do:
I need to call the check_login-Method (as below), which needs parameters.
redirect_to check_login_users_url(
:user => {:name => input[1], :password => input [2] },
:stylesheet => 'scaffold',
:method => :get)
The point is that these params are sent in the method-call as in the "Redirected to"-line below.
Processing ApplicationController#execute(for 127.0.0.1 at 2009-12-19 00:28:40) [POST]
Parameters: {"command"=>{"line"=>"log dodo wg"}, "authenticity_token"=> <...token>}
Redirected to http://localhost:3000/benutzer/check_login?method=get&stylesheet=scaffold&user%5Bname%5D=dodo&user%5Bpassword%5D=wg
Completed in 9ms (DB: 0) | 302 Found [http://localhost/execute]
I want to prevent rails from putting the params into the url and pass them hidden instead.
When I send a form created with form_for, there's nothing in the url, so I assume it must be possible.
Please tell me how to do that.
Steps tried
I have tried different "html-verbs": get, put, post - no difference. Though the call of check_login is really short the url-with-params shows up in my Console
create an instance variable and pass it as param (strange, didn't work either)
watch form_for working – without results, got no clue
//edith:
Thanks for all your help so far. Perhaps I didn't specify my problem in enough detail.
I've got a text_field in which I enter short commands (experimentally). Its form calls execute in AppController, which in case of login-data performs redirect_to check_login. I don't need to access a webpage, I simply want to run the method. I liked the idea of putting it into :flash, but I'm wondering if there's a "neater" way to do pass the data hidden.
TL; DR Version: Use a form.
You're never going to be able to fully hide parameters, tools can be used to monitor requests and view the post data/parameters. You could however obfuscate it with an encrypted session. Also it appears that you're sending login info via a GET request, this is generally a bad practice.
That said...
What is going wrong for you is that you're not generating any post data with link_to :method => :post. link_to will use what ever parmas you give it to generate the url. Wheres forms will send all the params generated by the form as POST data to the url generated in the form_for call.
Upon receiving a POST request, Rails will merge parameters routing picks up from from the URL with the post data it receives into one params hash.
As in POST to
http://localhost:3000/benutzer/check_login?stylesheet=scaffold&user%5Bname%5D=dodo&user%5Bpassword%5D=wg
produces the same params hash in the receiving controller action as a POST to http://localhost:3000/benutzer/check_login with the following data:
stylesheet=scaffold&user[name]=dodo&user[pasword]=wg
There will be no distinction in the server log between the two requests.
If you look at what form_for is doing, it submits POST data built from the form inputs to the url generated by the arguments.
form_for #user, create_user_url(:stylesheet => "scaffold") do |f|
f.text_field :name
f.password_field, :password
end
This form will submit the form data to the url generated from the options. In this example the url is: http://localhost:3000/users/create?stylesheet=scaffold and the form data is:
user[name]=name_field_value_at_submit&user[password]=password_field_value_at_submit
link_to will not populate post data for you. You must either do it through a form or with javascript. The link_to documentation contains an example of doing this with javascript. Look for how the destroy with :onclick is handled.
If you really don't like buttons, you could use link_to_function to submit a form.
Replace
:method => :get)
with
:method => :post)
What's the difference between :get and :post? Read Methods GET and POST in HTML forms - what's the difference?
With form_for you create form which is then POSTed to server, that's why you don't see parameters in url - they're in http request body. But it is not possible to redirect user's browser from some action in controller to make another POST - if it would be possible, then I could redirect user to (for example) email change form of gmail or other forms. You can only redirect user to other site, which user's browser then GETs.
If you really don't want to show parameters in url, and both actions are in same application, then you can store those parameters in session or flash store, and retrieve in next request after redirect.
You can use Ajax request to send form data to action :
In some cases its not good to change :get into :post.
For instance in case of Controller's :index action its not good approach to use :post
So Use ajax call to submit form and update only dynamic content of the page.
In js.coffe script file
$ ->
$("#button-id").on "click", (ev) ->
$.ajax
type: "GET"
dataType: "html"
url: "/horoscope_dailies"
data:
date: date
success: (data) ->
$("#index_content").html data
error: (object, error) ->
console.log error
In your controller action
render partial: 'partial_name' if request.xhr?
In your view file:
%div{:id => 'partial_content'}
= render 'partial_name'

Resources