1

I'm having a problem with form_for and fields_for.

So, my problem is:

  • I had a form_for, and inside this form_for, I use a fields_for. Inside this fields_for, I use a form_tag (i used ajax for this form_tag).
  • But when I view the generated HTML, it didn't display form_tag, it only display form_for. And I didn't understand why.
  • Please explain for me, why it didn't display form_tag.

Here is my form_for:

<div class="row">
  <%= form_for @real_estate, url: admin_real_estate_update_path do |f| %>
    <%= f.fields_for(:client) do |client| %>
      <%= text_field :real_estate, :assessment_start_at, value: @real_estate.assessment_start_at %>    
      <%= render partial: "admin/real_estate/form/assessment", locals: {real_estate_id: @real_estate.id} %>
    <% end %>
    <%= f.submit "Submut", class: "btn btn-primary"%>
  <% end %>
</div>

Here is my form_for which i put inside fields_for:

<%= form_tag admin_search_assessment_path(real_estate_id), method: :post, remote: true do %>
  <%= text_field_tag :company_name, params[:company_name] %>
  <%= submit_tag "Submit" %>
<% end %>

And i tried to add <form></form> follow as:

<div class="row">
  <%= form_for @real_estate, url: admin_real_estate_update_path do |f| %>
    <form></form>
    <%= f.fields_for(:client) do |client| %>
      <%= text_field :real_estate, :assessment_start_at, value: @real_estate.assessment_start_at %>    
      <%= render partial: "admin/real_estate/form/assessment", locals: {real_estate_id: @real_estate.id} %>
    <% end %>
    <%= f.submit "Submut", class: "btn btn-primary"%>
  <% end %>
</div>

And form_tag was display, but form_for didn't display.

Update:

So, i used $("form_2").submit(function() {....}); to solve this problem. Actually, i still want to use form-nested.

Khanh Pham
  • 2,848
  • 2
  • 28
  • 36
  • 4
    You cannot nest form tags. This is not valid HTML. See here: http://stackoverflow.com/questions/379610/can-you-nest-html-forms – AmitA Nov 11 '15 at 05:09
  • Thank you for your answer. But the second form (form_tag), i used ajax to submit data. So, do we have other cases to solve this problem ? – Khanh Pham Nov 11 '15 at 05:34
  • Then you need to make it a separate form, un-nested, with `remote: true`. – AmitA Nov 11 '15 at 05:53
  • @AmitA Thank for your answer, but follow as my project and my contest, i must work as form nested. So, do you have any advise for me ? – Khanh Pham Nov 11 '15 at 09:40
  • you cannot do what you are trying to do. It is not valid and the behaviour is undefined. – sevenseacat Nov 11 '15 at 09:44
  • You can't nest forms. Instead of having a structure of `
    ...
    ...
    ...` use the structure `
    ...
    ...
    ...
    `. You may need to duplicate fields, or "pair" fields in form a with hidden fields in form b using Javascript, but that's life. Your only other option is to use Javascript to submit data to the server, e.g. using jQuery's `$.ajax` function when the user performs some behavior. This will require you to write code that compiles the right data to send from the fields.
    – AmitA Nov 11 '15 at 15:04

1 Answers1

1

Inside this fields_for, I use a form_tag (i used ajax for this form_tag)

N'est pas possible, mon ami.

--

Here's how it works...

form_for and form_tag both generate pure HTML forms:

<form action="/action" method="POST">
</form>

Many people get confused about how Rails works - it's really quite simple. Rails employs "helper" methods to generate pure HTML which your browser can read.

Browsers only understand HTML/CSS at the moment. Thus, whenever you send a request to Rails - it has to return that data, otherwise a "web page" simply wouldn't be able to be processed.

Thus, when you ask whether you can nest forms, you have to abide by how the forms work in pure HTML (spec):

Note you are not allowed to nest FORM elements!

HTML fill-out forms can be used for questionaires, hotel reservations, order forms, data entry and a wide variety of other applications. The form is specified as part of an HTML document. The user fills in the form and then submits it. The user agent then sends the form's contents as designated by the FORM element. Typically, this is to an HTTP server, but you can also email form contents for asynchronous processing.

In short, it means that everything within a <form> tag is counted as a form by HTTP. This means that if you have another <form> tag, it's going to cause an error, preventing either from working.


You know this already (otherwise you wouldn't have mentioned ajax).

Your main problem is the use of <form></form> inside your current <form> object. This will confuse HTML profusely, and thus I would recommend replicating the submission of a form, without the <form> object itself:

#app/views/admin/real_estate/form/assessment.html.erb
<%= text_field_tag "[company_name]", params[:company_name], id: real_estate_id %>
<%= button_tag "Submit", type: "button" , data: { id: real_estate_id } %>

#app/assets/javascripts/application.js
$(document).on("click", "button", function(e){
   e.preventDefault();
   var real_estate_id = $(this).data("id");
   $.ajax({
      url: "path/to/real/estate/form/assessment/" + $(this).data("id")),
      data: {company_name: $("input[type=text]#" + real_estate_id).val()}
      success: function(data) {
         //do something on success
      },
      error: function(data) {
         //do something on error
      }
   });
});

This code will still output what you need.

The difference will be two-fold:

  1. The user will experience the same functionality (the input will still be present)
  2. The embedded form will be passed to the main "form" submit, but will not be passed through your strong params method (making it invisible to your controller)

In effect, you're replicating the functionality of an HTML form through Ajax. Whilst I still wouldn't do it this way, it will give you the functionality you require.

Richard Peck
  • 76,116
  • 9
  • 93
  • 147