Rails ajax form not submitting from within another - ruby-on-rails

I have a Rails 3.2 ajax form that creates a new Room for a Hotel. The new Room ajax form works correctly on the Room index page, but once I embed the new Room ajax form on a Hotel edit page, the form is submitted normally without using Ajax.
To create the new Room form, I use the following link on the Hotel edit.html.erb page:
<%#= link_to 'Add a Room', new_room_path(:hotel_id => #hotel.id), :remote => true, :class => 'new_room' %>
This loads the following form partial on to that same page:
<%= form_for #room, :remote => true, :html => { :class => "remote-form" } do |f| %>
<%= f.text_field :number %>
<%= f.text_field :size %>
<% if(params.has_key?(:'hotel_id')) %>
<% #hotel_id = params[:hotel_id] %>
<%= f.hidden_field :hotel_id, :value => #hotel_id %>
<% else %>
<%= f.collection_select(:hotel_id, Hotel.all, :id, :name) %>
<% end %>
<%= f.submit "Add this room", :class => 'room_create' %>
<%= link_to 'Cancel', '#', :class => "room_cancel" %>
<% end %>
And finally, I have the following in my create.js.erb (inside the rooms folder):
alert('Test creating a room');
var content = $('<%= escape_javascript(render(#room)) %>');
$("#room_list tbody").append(content);
The create.js.erb is not executed and the form is submitted regularly (non-ajax) and I finally arrive on the room show.html.erb page.
Why is the form be working correctly on the Units index page, but not on the associated Hotel edit page?

Even when you set :remote => true, Rails generates a form tag. Nested form tags are not supported by browsers and will result in unpredictable behavior.
You should rethink the views architecture here. Probably you can have the forms for the rooms outside of the form for the hotel, or maybe you can use fields_for and accepts_nested_attributes_for to edit children objects.
Here's a full example on how to use nested attributes: Nested Attributes Examples.

You cannot nest a form inside a form in HTML. When you click any submit button on a form, even if it's inside another form, only the outermost form will be properly submitted.
You can either use nested attributes to add the attributes for the room directly to the form, so that when the overall form is submitted so are all the rooms... or use a div and a link, instead of a form and a submit button.

Related

Passing form to partial with remote true update - Rails

I'm using Rails 5.2.2. I have a form with remote: true. I have a partial that displays shipping methods where I render nested shipping methods available for a quote. My form accepts nested attributes also.
My form works fine, but on update I am wanting to render the updated shipping methods if they have changed but since I pass the original form to my partial, I don't have that variable available on update. Here is my partial
_shipping_rates.html.erb
<h2> Shipping Rates</h2>
<div id="quote-shipping-rates">
<%= form.collection_radio_buttons(:shipping_method_id, quote.shipping_methods.sort_by(&:price), :id, :name, { checked: quote.shipping_method_id }) do |b| %>
<%= b.radio_button %>
<%= b.label %>
(<span class="text-red"><%= number_to_currency(b.object.price) %></span>)
<br />
<% end %>
On the initial page load I call the partial like this:
<%= render 'shipping_methods', :form => u , :quote => #quote %>
On update, I have the following file that executes JavaScript to update the DOM.
update.js.erb
I want to do something like this but I wasn't sure if there was some Rails way to recreate the form variable and pass it to the partial.
$("#quote-shipping-rates").html("");
$("<%= escape_javascript(render :partial => "shipping_methods", :form => u , :quote => #quote) %>").appendTo("#quote-shipping-rates");

Rails pass parameter with submit

I have a Rails 3.2.12 app where I would like to pass a parameter via a form submit button.
The param is :invoice_id. In the form the value is in #invoice.
I tried this:
<%= f.submit "Submit", :class => "btn btn-success", params: {:invoice_id => #invoice} %>
In the controller, I would access it like this:
def addinvtimes
#invoice = params[:invoice_id]
But, it ends up being nil.
Thanks for the help!
UPDATE1
That's not how HTML forms work. If there's data that you want to get submitted along with the rest of your form's data but not be viewable or editable by the user, stuff it into a hidden field, like so:
<%= form_for #order do |f| %>
<%= f.text_field :customer_name %>
<%= f.hidden_field :invoice_id, value: #invoice.id %>
<% end %>
When you do this, the invoice_id will be submitted alongside the rest of the form's data, so in this case you would access it as params[:order][:invoice_id].

Ajax form within a form with no layout

So I'm new to rails and having a little bit of trouble my situation is that I have a products model that has some Images attached to it. I would like on my products page to have a button to create a new image via ajax.
Inside my products _form view i have:
<%= simple_form_for(#product) do |f| %>
<%= f.error_notification %>
<div class="inputs">
<%= f.input :name %>
<%= f.input :description, :input_html => {:class => "wysihtml5 span6", :style => "height:400px;"} %>
<%= f.association :images, label_method: :name, value_method: :id %>
<h4>Upload new file</h4>
</div>
<%= link_to 'Add Image', '/images/new', :remote => true, :"data-replace" => "#image-form" %>
<div id="image-form">
</div>
<div class="actions">
<%= f.button :submit %>
</div>
<% end %>
And it does successfully Load the page via ajax.
But I would like to load it without the layout. Is this possible?
Do I need to create a new action that renders the partial form and has no layout??
So I'm assuming you have it requesting and returning html and not js? There are a couple of thoughts I have on this:
If you only ever need for this request to return from an AJAX request, then you could simply tell the controller to always render layout: false
If you would like to allow the controller to return a full page on occasion, you can either accept an argument in the get request and change the output accordingly, or you can tell the controller to:
respond_to do |format|
format.html # will render default with no block passed
format.js { render layout: false }
end
This should just work with the code in your form right now, because the :remote => true tells the controller to return js if possible, but accessing images/new from your browser will request html.
(Requesting js does not mean that you actually have to return js, as I don't in this case; it's up to you to take the proper action with what is returned. Some might consider it bad form, though, to return something other than what is technically requested.)
You can use the following in your action. Let your action is new.
def new
#your code goes here
render :layout => false
end

Rails 3 submit form with link

How I can submit form with link on correct rails 3 format?
Thanks.
<%= form_for #post do |f| %>
<%= f.label :title %><br>
<%= f.text_field :title %>
<p><%= f.submit %></p>
<% end %>
My code sample.
For people who came here via Google, I have an improvement on Zequez's answer. Instead of the method that he gives, add this method to the application helper instead:
def link_to_submit(*args, &block)
link_to_function (block_given? ? capture(&block) : args[0]), "$(this).closest('form').submit()", args.extract_options!
end
Then, as Zequez stated, for simple links you can just do this in your view:
<%= link_to_submit 'Submit Form' %>
...and for more complicated buttons you can pass HTML options and a block to be used inside the link. If you use Twitter Bootstrap, for example, this lets you add CSS classes, formatting and icons:
<%= link_to_submit( class: 'btn btn-primary' ) do %>
<strong>Submit</strong> the Form <i class="icon-arrow-right"></i>
<% end %>
The JQuery code will work as long as the link is a child of the form (that is, as long as link_to_submit is called from somewhere within the form_for block).
"Correct" is a tricky word in this context ;) . One could ask why you're not just taking a button element and make it look like a link?
Anyways — you can't achieve this with plain HTML (at least not to my knowledge). With a Javascript framework like e.g. jQuery you could simply do something like this:
$('a').click(function(){
$('form').submit();
return false;
});
Rails 2.3.x had a link_to_remote helper which let's you specify a :submit parameter (= DOM element's ID, default is the parent form). So you were be able to write:
link_to_remote 'submit', :url => {…}, :submit => "my_form"
But with Rails 3's push to UJS, this helper is gone.
You can add the following to the application helper:
def link_to_submit(text)
link_to_function text, "$(this).closest('form').submit()"
end
Then inside your view files you can just call
link_to_submit 'Submit Form'
And the link must be child of the form.
With jquery, this one-liner will work fine for a simple form.
<%= link_to t("translate.submit"), "#", class: "make it beautiful", :onclick=>"$('form').submit()" %>
Of course you don't really have to use jquery, just finding the dom element for your form will work fine as well.
<%= link_to t("translate.submit"), "#", class: "make it beautiful", :onclick=>"document.getElementById('your_form_id').submit()" %>
This way you don't use any ajax, just plain form submit.
In Rails 3, the link_to_remote helper is gone, but it's replaced with
link_to 'submit me', url_for(#post), {:remote => true, :class => 'submit_me'}
In your case, you likely want your form to do the AJAX, like so:
<%= form_for #post, :remote => true do |f| %>
<%= f.label :title %><br>
<%= f.text_field :title %>
<p><%= f.submit %></p>
<% end %>
With a companion link:
link_to 'submit me', '#', :class => 'submit_me'
Then, in an .js file included in the page body:
$('.submit_me').click(function() {
$('form').submit();
return false;
});
The idea is that anything more complicated than turning a link or form into an ajax request should be done with the jQuery callbacks, as listed here:
https://github.com/rails/jquery-ujs/wiki/ajax
And if you want to really get into interactive AJAX requests, go here for a great 2-part article on it.

How to produce several forms for a nested form?

Intro
I have an object #organization that has_many :quick_facts
Basically, I want to produce a _form for each :quick_fact but with one save button, that saves all of the quick_facts.
My two problems:
First Problem:
My quick_facts are not prepopulated with their information. They only appear as blank for each quick_fact I have.
Second Problem
A save button appears on every single form
My sad sad attempt :
- for quick_fact in #organization.quick_facts
- fields_for :quick_facts do |f|
= f.error_messages :header_message => FORM_ERROR_HEADER_MESSAGE, :message => FORM_ERROR_MESSAGE
= f.label :quick_fact, 'QuickFact'
%br/
= f.select :quick_fact, QUICK_FACTS, {}
%br/
= f.submit 'save', :class => 'button'
You really just want one form here, since you want to submit everything at once.
Here is what I would recommend:
Use a partial to render the label and the text option for the quick fact (if you want it to be text). You want this partial to be rendered once per quick fact, so use the :collection option on the render method to specify the collections of quick facts. Each partial will get its own local copy of whatever quickfact you are on, and a variable called quickfact_counter will also be created.
In addition, you will want to use the :locals option to pass the form to the partial as a local variable, so that you can do f.label, f.text_area
So, in conclusion, your new form will be something like this:
<% form_for #organization do |form| %>
<%= render :partial => "partial_name", :collection => #organization.quick_facts, :locals => {:form => form} %>
<%=form.submit 'save', :class => 'button'%>
<% end %>
Then your partial will just have
<%= form.label :quick_fact, 'QuickFact' %>
<%= form.text_field :quick_fact %>
If you wanted to get even fancier you could use a layout to render the form and have it defer to the partial, but this should be enough to get you started. Being able to pass a collection to a partial is one of my favorite Rails features.

Resources