Rails Turbolinks does not render response from submitted form - ruby-on-rails

Submitting a basic xhr-form in a turbolinks-activated rails project (5.1), does trigger the correct server-side response but the client (turbolinks) discards the response. Neither get nor post do work. Tested in Firefox and Chromium. Forms with redirection work as intended.
Here's a simple test page that fails for me
test.html.erb:
<h1><%= #value %></h1>
<%= form_with url: 'test' do |f| %>
<%= f.check_box :anything %>
<%= f.submit %>
<% end %>
controller:
def test
if request.post?
#value = 'post'
else
#value = 'get'
end
end
routes:
post '/test', to: 'controller#test'
get '/test', to: 'controller#test'
rails response payload:
<h1>post</h1>
<form action="test" accept-charset="UTF-8" data-remote="true" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="X1sh+tc/Jx4P0rdDqc2CD1RetKQKr+lVh4fD29JOMY/b+PdPNgw1qyzoyv6t3I2I+6jV1mmn6voXN+YySaUISw==" />
<input name="anything" type="hidden" value="0" /><input type="checkbox" value="1" name="anything" />
<input type="submit" name="commit" value="submit" data-disable-with="submit" />
</form>
</div>
The form loads like expected, but after submitting the page does not change. Inside the xhr-response the correct answer is visible, but it does not get applied to the DOM.
Is this a bug, or am I using turbolinks wrong?

I'm seeing this as well and I'm not sure how to proceed. What is nice about Turbolinks is that you don't have to create js responses for each request. This is true until you submit a form. At that point, you have no choice but to create a js.erb respone file or change the form to local: true. Am I missing something?

Try using data: { turbolinks: false } in the any links to the page containing the form.
E.g.
<%= link_to "Get in Touch", 'contact', data: { turbolinks: false } %>

Related

Rails generate wrong method for "form_tag". How to fix that?

On on page, I have 2 forms like this:
<%= form_tag(create_car_service_settings_index_path, remote: true, method: :post) do %>
<%= hidden_field_tag "service_type", 1 %>
<%= text_field_tag "service_name", "", id: "service_name_car" %>
<%= submit_tag "Add Service" %>
<% end %>
... some HTML ...
<%= form_tag(create_car_service_settings_index_path, remote: true, method: :post) do %>
<%= hidden_field_tag "service_type", 0 %>
<%= text_field_tag "service_name", "", id: "service_name_car" %>
<%= submit_tag "Add Service" %>
<% end %>
The first form is rendered as POST, but the second one as GET; in routes.rb is following:
resources :settings do
collection do
...
post 'create_car_service'
post 'edit_car_service'
end
end
Why the second form is rendered as GET instead of POST? Stuck on this for a while.
Thanks.
EDIT:
First form:
<form action="/settings/create_car_service" accept-charset="UTF-8" data-remote="true" method="post">
...
Second form:
<form action="/settings/create_car_service" accept-charset="UTF-8" data-remote="true" method="get">
When you do bin/rails routes you should get something like this
Prefix Verb URI Pattern Controller#Action
create_car_service_settings POST /settings/create_car_service(.:format) settings#create_car_service
edit_car_service_settings POST /settings/edit_car_service(.:format) settings#edit_car_service
So that post route should be create_car_service_settings_path not create_car_service_settings_index_path that points to settings#create_car_service
But it is a strange if you get for one method GET and other POST. Can you paste the output from these forms (html)
EDIT
So using the path that you provided generated an error for me. When I use this
<%= form_tag(create_car_service_settings_path, remote: true, method: :post) do %>
I will get this for first
<form action="/settings/create_car_service" accept-charset="UTF-8" data-remote="true" method="post">
for second
<form action="/settings/create_car_service" accept-charset="UTF-8" data-remote="true" method="post"><input name="utf8" type="hidden" value="✓" />
<input type="hidden" name="service_type" id="service_type" value="0" />
<input type="text" name="service_name" id="service_name_car" value="" />
<input type="submit" name="commit" value="Add Service" data-disable-with="Add Service" />
</form>

routing form submission to different controller

problem: I have a form but the submit button doesn't do anything.
i instantiate the class the form is for in the employee_controller controller.
def employee
#body_class = "employee membership"
#employee_contact_form = CorporateContactForm.new
end
I create the form in the page the above controller action serves
= simple_form_for [#employee_contact_form] do |f|
= f.input :firstname
= f.button :submit
In my routes I set the resources for the contact forms
resources :corporate_contact_forms
I then have a controller that serves the form
class CorporateContactFormsController < ApplicationController
def create
raise
end
I am aware there is no code in the corporatecontactcontroller, but the submit button should at least fire to an error. It doesn't do anything.
This feels like such a simple problem, and surely it is.
What am I missing?
update
html output
<form>
<form accept-charset="UTF-8" action="/corporate_contact_forms" class="simple_form new_corporate_contact_form" id="new_corporate_contact_form" method="post"><div style="display:none"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="7iMwWQOuyzV3jJt4jTtr9MGvI129hPaG+m+Pe2D3YyM=" /></div> <div class="input string optional corporate_contact_form_firstname"><label class="string optional" for="corporate_contact_form_firstname">Firstname</label><input class="string optional" id="corporate_contact_form_firstname" maxlength="255" name="corporate_contact_form[firstname]" size="255" type="text" /></div>
<input class="button" name="commit" type="submit" value="Create Corporate contact form" />
</form>
</form>
According to the documetation (http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for), you can do something like this to force the form to go to CorporateContactFormsController#create
<%= simple_form_for #employee_contact_form, url: corporate_contact_forms_path, method: :post do |f| %>
# awesome code...
<% end %>
Also I'm not sure if the f.button :submit has something to do, the default for submitting is f.submit

form_tag with :remote => true does not update div, skips to separate page

I am trying to update a div based on a form submit. I am on Rails 3.1.1. I am trying to adapt someone else's recipe. My code in the view is something like this in main.html.erb:
<%= javascript_include_tag :defaults %>
<div id='seq_search'>
<%= form_tag(:remote => true, :update => 'seq_select', :action => 'select') do %>
<p>
<%= search_field_tag :query, '', :size => 45 %>
</p>
<p>
<%=submit_tag "Submit", :disable_wth => "Adding ..."%>
</p>
<% end %>
</div>
<div id='seq_select'>
</div>
The controller looks like
class SearchAjaxController < ApplicationController
def main
end
def select
render :text => '<li> '+params[:query] + ' </li>'
end
end
However, when I enter something in the text box and press submit, instead of updating the div, it goes off to another page rendering just the output of the select method of the controller.
If I look at the page source of the form, it is something like this:
<div id='seq_search'>
<form accept-charset="UTF-8" action="/search_ajax/select?remote=true&update=seq_select" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="wlOm4H7GvZAQoIVpjxPLqHAQLOIpJ4V5r0WYEpvCCrQ=" /></div>
<p>
<input id="query" name="query" size="45" type="search" value="" />
</p>
<p>
<input disable_wth="Adding ..." name="commit" type="submit" value="Submit" />
</p>
</form></div>
<div id='seq_select'>
</div>
It seems that the form is simply passing remote=true&update=seq_select as arguments to the controller's method/function. Is this what is supposed to happen?
Update:
So I tried to add to follow Mike Campbell's sugggestion and added the following code to my view (`.html.erb') file
<SCRIPT type='text/Javascript'>
$(function(){
$('#form-id').bind('ajax:success', function(xhr, data, status){
$('#seq_select').html(data);
});
}
</SCRIPT>
and also gave an id to the form:
<%= form_tag(:remote => true, :update => 'seq_select', :action => 'select', :id => 'form-id') do %>
Submitting the form still doesn't update the page. It simply skips to a new rendered view as before. The generated HTML reads:
<SCRIPT type='text/Javascript'>
$(function(){
$('#form-id').bind('ajax:success', function(xhr, data, status){
$('#seq_select').html(data);
});
}
</SCRIPT>
<div id='seq_search'>
<form accept-charset="UTF-8" action="/ajax_search/select/form-id?remote=true&update=seq_select" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="wlOm4H7GvZAQoIVpjxPLqHAQLOIpJ4V5r0WYEpvCCrQ=" /></div>
<p>
<label> Search by identifiers, accessions, and gene names.. </label>
</p>
<p>
<input id="query" name="query" size="45" type="search" value="" />
</p>
<p>
<input disable_wth="Adding ..." name="commit" type="submit" value="Submit" />
</p>
</form></div>
<div id='seq_select'>
</div>
Update:
It seems that the syntax for form_tag was wrong, and the first argument has to be the name of the action. I now have <%= form_tag( 'select', :remote => true, :id => 'form_id') do %> which generates the associated HTML <form accept-charset="UTF-8" action="select" data-remote="true" id="form_id" method="post">. Which is better, but my Ajax is still not working.
I think this has to do with respond to xhr in the controller. you should specify this is a xhr request.
See here for a question on that.

How to create a delete form with RESTful routes in Rails.

I am trying to create a form that serves as confirmation for the destroy method on a controller. In my routes I have:
resources :leagues do
get 'delete', :on => :member
end
In my delete.html.erb, I have the following for:
<% form_for current_league, :html => {:method => :delete} do |form| %>
<%= form.submit 'Yes' %>
<%= form.submit 'No', :name => 'cancel' %>
<% end %>
current_league is a helper function defined by:
def current_league
#current_league ||= League.find_by_id(params[:id])
end
So the problem is that the form that is generated only edits the league model, as seen by the form method="post".
<form accept-charset="UTF-8" action="/leagues/1" class="edit_league" id="edit_league_1" method="post">
<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" />
<input name="_method" type="hidden" value="delete" />
<input name="authenticity_token" type="hidden" value="abcdefg" />
</div>
<input id="league_submit" name="commit" type="submit" value="Yes" />
<input id="league_submit" name="cancel" type="submit" value="No" />
</form>
How can I fix this?
I think that will already work. As in rails guide http://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-patch-put-or-delete-methods-work-questionmark
However, most browsers don’t support methods other than “GET” and “POST” when it comes to submitting forms.
Rails works`around this issue by emulating other methods over POST with a hidden input named "_method", which is set to reflect the desired method:
as you see in the output form there is
<form accept-charset="UTF-8" action="/leagues/1" class="edit_league" id="edit_league_1" method="post">
....
<input name="_method" type="hidden" value="delete" />
....
</form>
When reading this variable, rails understood that this is a DELETE method, not a POST method. even though the form it self is a POST.

Why is simple_form not creating my fields and creating hidden fields instead?

This is my ruby code:
<%= simple_form_for([#video, #video.comments.new]) do |f| %>
<% f.association :comment_title %>
<% f.input :body %>
<% f.button :submit %>
<% end %>
This is the generated HTML markup:
<form accept-charset="UTF-8" action="/videos/485/comments" class="simple_form comment" id="new_comment" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓">
<input name="authenticity_token" type="hidden" value="55xSU8JUe1SgipjAkAEvCvidFdJY3hv8Qz5VBqUSrdE=">
</div>
<input class="button" id="comment_submit" name="commit" type="submit" value="Create Comment">
</form>
Obviously it's not creating the :body input field and the association select list correctly. Why is this and how can I fix it?
Btw, a video has many comments, and a comment belongs to video. Also, a comment_title has many comments, and a comment belongs to a video. Comment_title is generated with virtual attributes.
Please let me know if there is any other code you would like to see.
Both of these are because of choices in your rails application. The first is that you have selected to configure the application to use utf8 for character encoding. The second is because by default the application is setup to protect against cross site request forgery attacks. The authenticity token ensures that the response coming back to the server when the user submits the form is actually from you and not some other source just watching your traffic and posting away to mess with your database.
Ok so the problem was that I needed to add the "=" to <%= in my form elements.

Resources