How to produce several forms for a nested form? - ruby-on-rails

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.

Related

Rails ajax form not submitting from within another

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.

Rails partial view set value of form field

Okay so I am quite new to Rails and am trying to do the following without success:
I have an Object (from my Active Record) containing a project, which contains n sub-projects, which contain n tasks. Now for each of these I want a partial view.
So I render from the project view the sub-project with the following code:
<%= render(:partial => 'subproject', :collection => #project.sub_projects) %>
Within my sub-project partial view called _subproject.rhtml (adding the code to a good ol Rails 1.2.3 project), so I can access the data like this:
<%= subproject.name %>
That will print out the name alright but when I try to generate a textfield this won't work:
<%= text_field 'subproject', 'name' %>
But this will:
<%= text_field 'subproject', 'name', :value => subproject.name %>
What am I doing wrong?
Edit: Changed title due to my problem is not passing the value but displaying it within a form field.
Edit2: As requested my controller code:
#project = Project.find(params[:id])
You can write this:
<%= render(:partial => 'subproject', :collection => #project.sub_projects) %>
as
<%= render :partial => #project.sub_projects %>
This will render every sub project with the sub_projects/_sub_project.html.erb partial. A little shortcut.
This:
<%= text_field 'subproject', 'name' %>
Says create a text_field called: subproject[name], but doesn't give it a value. You need to pass the value you want to set (the code that works).
The more idiomatic way of doing this now is with form_for:
<% form_for #subproject do |f| %>
<%= f.text_field :name %>
<% end %>
Or if you're using formtastic (https://github.com/justinfrench/formtastic), which is fantastic, you'd write:
<% semantic_form_for #subproject do |f| %>
<%= f.input :name %>
<% end %>
I hope this helps!

Reusing form nested and not nested, how to show submit button

I'm learning rails and building a recipe app.
In my app, a Recipe has a bunch of ingredients.
I've got my ingredients form nested within my recipe form, and I call it with a partial.
Of course, because the form is nested, the <%= f.submit %>
is in the recipes/_form.html.erb page.
So now I'm trying to edit a single ingredient outside the nested form. I want to use the same form though as it is still an ingredient. So I've created
<% form_for :ingredients, #ingredient, :url{:action =>'update', :id=>#ingredient.id} do |f| %>
<% render :partial => 'form', :locals => {:f=>f} %>
<%= f.submit %>
<% end %>
for some reason, this results in only the submit button being shown.
If I put the submit button inside the partial, it would show up within the recipe form which just isn't right.
You are missing the = operator while trying to render the partial, it should be:
<%= render :partial => 'form', :locals => { :f => f } %>
It should work, hope it helps you!

Forms blank when rendering a partial when using a collection of objects. Help!

Alright, I know my title is a little obscure but it best describes the problem I am having.
Essentially, I have a list of users, and want to be able to edit their information in-line using AJAX.
Since the users are showing up in rows, I am using a partial to render the data and the forms (which will be hidden initially by the ajax), however, when the rows are rendered currently only the last item has it's form's fields populated.
I suspect this has something to do with the fact that all the form fields have the same id's and it is confusing the DOM. But I don't know how to make sure the id's are unique.
Here is a small example:
In my view:
<%= render :partial => 'shared/user', :collection => #users %>
My partial (broke down to just the form) note that I am using the local variable "user"
<% form_for user, :html => {:multipart => true} do |f| -%>
<%= f.label :name, "Name*" %>
<%= f.text_field :title, :class => "input" %>
<%= f.label :Address, "Address" %>
<%= f.text_field :address, :class => "input" %>
<%= f.label :description, "Description*" %>
<%= f.text_area :description, :class => "input" %>
<% end -%>
When the html is rendered each form has a unique id (for the id of the user) but the elements themselves all have the same id, and only the last user form is actually getting populated with values.
Does anyone have any ideas?? :)
Thanks in advance!
Alright, after having some lunch and regaining some brain cells, (and with a little help from Google) I figured this one out.
When passing a collection to a partial like this:
<%= render :partial => 'shared/user', :collection => #users %>
Rails creates a counter variable that you can use to define an index for the form in the form of "variable_counter":
<% form_for user, :index => user_counter, :html => {:multipart => true} do |f| -%>
This adds the index number to the form id as well as all the field id's and solved my little problem. :)
I hope this helps out someone else with this issue. :)

passing in parent id to remote_form partial on item creation

I am still kind of fuzzy on controllers in rails, especially so because a lot of things seem to happen magically behind the scenes, and that's not happening in this case.
So say I have a person model, which has many photos (using paperclip) and has many favorite quotes. The quotes can have the text, the attributed author, etc. In both of those models, they are set as belonging to my person model.
Within a new person form, I used some code elsewhere to create a new photo:
<% form.fields_for :screenshots, :html => { :multipart => true } do |screen_form| %>
<%= render :partial => 'screenshot', :locals => { :form => screen_form } %>
<% end %>
The partial for that is very simple, like this (minus some ajax javascript stuff I put in for nested models):
<%= form.label :photo, "Screenshot:" %>
<%= form.file_field :photo %>
This all works fine and magically the ID of the person is associated with a screenshot upon creation in person_id. I don't even have a controller for screenshots and it still works.
However, it's not working for my quotes.
<% remote_form_for :quote, :html => { :method => :put }, :url => {:controller => "quote", :action => "create", :person_id => #person.id} do |quote_form| %>
<%= render :partial => 'quote', :locals => { :form => quote_form } %>
<% end %>
The partial for this is also very simple.
<%= form.label :quote_text %>
<%= form.text_field :quote_text %>
.........
<%= form.submit 'Create' %>
I am not really sure if I can put person ID in there, but it didn't complain. However it didn't work, either. The quotes controller is very simple.
def create
#quote = Quote.create(params[:quote])
end
Currently it gets put in the DB but person_id is not populated so I can't pull up the quotes associated with a particular person. Sorry if this is a silly question, but I'm kind of learning Rails by tweaking tutorials and mashing them together so bear with me :) It's just kind of mysterious how the photo thing works with NO controllers or special stuff and this doesn't.
The first form is a person form mainly that has snapshots fields associated to it, so looking at your HTML you will find something like person[snapshots][photo], this form will be submitted to person controller.
Passing person id to second form the is key to make it work, however it's a bit weird that it's not working, the form will submit to quote controller. Did you make sure(watch the log) that the params hash has person_id attribute?

Resources