Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails - how to send a form that is inside another form?

I have this structure in my view:

<%= simple_form_for @user ... %>
  ...
  ...
  <%= render '/hobbies/form', :user => @user %>
  ...
  ...
<% end %>

The render part loads data from a partial - there's a form. The form-fields are successfully loaded (like inputs, submit input, radio buttons etc), but when I take a look at the generated HTML, in the rendered form is missing <%= form_for... and the closing tag.

Which means when I click to the submit button from the rendered form, this rendered form is not sent out, but instead of it is sent out the "big" for - simple_form_for.

How to make the rendered form sendable?

Thank you

like image 781
user984621 Avatar asked Aug 02 '14 14:08

user984621


2 Answers

Simply, you can't have two separate nested forms.

You can have nested associated forms using accepts_nested_attributes_for - this is dependent on the structure of your models in the backend, which I'll detail below.

--

Forms

The most important thing you need to know is that Rails just builds HTML forms - which means they have to abide by all the constraints & rules these forms stipulate:

enter image description here

Each form has its own action attribute - which is how your browser knows where to send the data. If you have multiple / nested forms, you'll basically have two of these "action" attributes; preventing HTML from sending the form correctly

--

Nested

If you want to use some Rails conventions, you'll be better using the accepts_nested_attributes_for method. This resides in the model, and in order to use it effectively, you need to ensure you have your ActiveRecord associations set up correctly:

#app/models/user.rb
Class User < ActiveRecord::Base
   has_many :hobbies
   accepts_nested_attributes_for :hobbies
end

#app/models/hobby.rb
Class Hobbies < ActiveRecord::Base
   belongs_to :user
end

The importance of the association is crucial - Rails will pass "nested" model data through to each other. The nested model data is only there if the models are associated correctly with ActiveRecord (as above)

You can then pass the data through your controller / models as follows:

#app/controllers/users_controller.rb
Class UsersController < ApplicationController
   def new
       @user = User.new
       @user.hobbies.build # -> essential for nested attributes 
   end

   def create
      @user = User.new(user_params)
      @user.save #-> notice how this saves the @user model only?
   end

   private

   def user_params
      params.require(:user).permit(:user, :attributes, hobbies_attributes: [:hobbies, :attributes])
   end
end

This will allow you to include the hobbies part of the form as follows:

<%= form_for @user do |f| %>
   <%= f.fields_for :hobbies do |h| %>
       <%= h.text_field :your_attributes %>
   <% end %>
<% end %>
like image 192
Richard Peck Avatar answered Oct 11 '22 15:10

Richard Peck


Nested forms is not valid html. To achieve this you have to either un-nest your forms or use javascript. If you opt for the javascript approach, you simple catch the form submit event, prevent the default, and manually submit the form you want.

EDIT:

If you opt for the javascript approach, consider that you might not need two forms at all. Instead you can just add a click handler for the button on your 'sub action' which makes an ajax request.

Alternatively, if javascript is not an option, and rearranging the html is not an option, you could handle this on the server by submitting the data from both forms and processing each differently depending on which submit input was clicked.

like image 37
Dane O'Connor Avatar answered Oct 11 '22 15:10

Dane O'Connor