I am having trouble creating multiple model objects using nested attributes. The form .erb I have:
<%= f.fields_for :comments do |c| %>
<%= c.text_field :text %>
<% end %>
is generating input fields that look like this:
<input type="text" name="ad[comments_attributes][0][text]" />
<input type="text" name="ad[comments_attributes][1][text]" />
<input type="text" name="ad[comments_attributes][2][text]" />
when what I really want is for it to look like this:
<input type="text" name="ad[comments_attributes][][text]" />
<input type="text" name="ad[comments_attributes][][text]" />
<input type="text" name="ad[comments_attributes][][text]" />
Using form helpers, how can I make the form create an array of hashes like I have in the second example, instead of a hash of hashes as it does in the first?
You could use text_field_tag for this particular type requirement.
This FormTagHelper provides a number of methods for creating form tags that doesn’t rely on an Active Record object assigned to the template like FormHelper does. Instead, you provide the names and values manually.
If you give them all the same name and append [] to the end as follows:
<%= text_field_tag "ad[comments_attributes][][text]" %>
<%= text_field_tag "ad[comments_attributes][][text]" %>
<%= text_field_tag "ad[comments_attributes][][text]" %>
You can access these from the controller:
comments_attributes = params[:ad][:comments_attributes] # this is an
array
The above field_tag html output look like this:
<input type="text" name="ad[comments_attributes][][text]" />
<input type="text" name="ad[comments_attributes][][text]" />
<input type="text" name="ad[comments_attributes][][text]" />
If you enter values between the square brackets, rails will view it as a hash:
<%= text_field_tag "ad[comments_attributes][1][text]" %>
<%= text_field_tag "ad[comments_attributes][2][text]" %>
<%= text_field_tag "ad[comments_attributes][3][text]" %>
would be interpreted by the controller as a hash with keys "1", "2" and "3".
I hope i understand correctly what you needed.
Thanks
Related
The following form allows the changing of an attribute vie UJS, the returning block of HTML is rendered correctly
<% #product.productviews.each do |productview| %>
<%= form_with(url: update_productview_products_path(productview_id: productview.id), method: :patch) do |form| %>
<%= productview.active %> <%= form.check_box :active %>
<%= form.submit t('update') %>
<% end %>
<% end %>
Class Product is a parent of has_many :productviews. context: rails 6.1.3
However when refreshing the page the check_box is invariably set to false, notwithstanding the value of the attribute:
<form action="/products/update_productview?productview_id=1" [...]
true <input name="active" type="hidden" value="0" /><input type="checkbox" value="1" name="active" id="active" />
<form action="/products/update_productview?productview_id=2" [...]
true <input name="active" type="hidden" value="0" /><input type="checkbox" value="1" name="active" id="active" />
<form action="/products/update_productview?productview_id=3" [...]
true <input name="active" type="hidden" value="0" /><input type="checkbox" value="1" name="active" id="active" />
<form action="/products/update_productview?productview_id=4" [...]
false <input name="active" type="hidden" value="0" /><input type="checkbox" value="1" name="active" id="active" />
Which is unexpected. Rails guides specify that Array parameters do not play well with the check_box helper. This instance is not a case of array parameters, although it is an array of forms.
However switching to <%= form.check_box_tag "active" %> or <%= form.check_box_tag :active %> will return
undefined method `check_box_tag' for #<ActionView::Helpers::FormBuilder:
which again seems contrary to what the Rails guides purport
Can check_box be used in an array of forms? How can this checkbox show the value of the attribute on page load?
you need to pass the model to the form
<%= form_with(url: update_productview_products_path(productview_id: productview.id), method: :patch, model: productview) do |form| %>
if this does not work you can pass a checked into the check_box input but I advise to use the first option if its working
<%= form.check_box :active, checked: productview.active %>
I'm going through Michael Hartl's Rails tutorial. One of the exercises for chapter 8 is to rewrite the code using form_tag instead of form_for. After viewing the source that form_for was giving me and looking up each tag in the Rails documentation, I was able to successfully put it together.
My question is: How does Rails know what id attribute to give the <input> tag created by text_field_tag, so that it matches the id of the <label> tag created by the label_tag that precedes it?
Here's the code for the form:
<%= form_tag(sessions_path) do %>
<%= label_tag "session_email", "Email" %>
<%= text_field_tag "session[email]" %>
<%= label_tag "session_password", "Password" %>
<%= password_field_tag "session[password]" %>
<%= button_tag("Sign in", name: "commit", type: "submit") %>
<% end %>
Here's the resulting html:
<form accept-charset="UTF-8" action="/sessions" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="c9a5KJveRSOQyDo/ckUtpmQAbjw2f1alnB6Dn1lu3XU=" /></div>
<label for="session_email">Email</label>
<input id="session_email" name="session[email]" type="text" value="{:id=>"session_email"}" />
<label for="session_password">Password</label>
<input id="session_password" name="session[password]" type="password" value="{:id=>"session_password"}" />
<button name="commit" type="submit">Sign in</button>
Note that since Rails 5.1, the recommended form helper to use is form_with.
And form_with no longer automatically generates id's and class's for DOM elements any more like form_for and form_tag used to.
This has implications for adding markup like labels which used to link up to their corresponding input fields automatically. Now, for a label to properly pair up to an input field (with the for attribute) you need to explicitly add the id attribute to the input.
Example
ERB:
<%= form_with model: User.new do |f| %>
<%= f.label :name %>
<%= f.text_field :name, id: :user_name %>
<% end %>
which generates HTML:
<form action="/users" method="post">
<label for="user_name">Name</label>
<input id="user_name" type="text" name="user[name]">
</form>
See also
https://medium.com/#tinchorb/form-with-building-html-forms-in-rails-5-1-f30bd60ef52d, specifically the heading "No more auto-generated ids and classes".
I am working on the front-end part of a Rails 3.1 application. We are using a Twitter Bootstrap as CSS Framework, Devise as the authentication manager and the I18n gem for localization.
This is the devise syntax for a checkbox with its label
<%= f.label :remember_me %>
<%= f.check_box :remember_me %>
And this of course is the generated HTML
<label for="user_remember_me">Ricordati di me</label>
<input name="user[remember_me]" type="hidden" value="0">
<input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
Since Bootstrap adds this rule for the labels display: block, the label and the checkbox are not in the same line. To have the on the same line I need an HTML output like this
<label for="user_remember_me">
Ricordati di me
<input name="user[remember_me]" type="hidden" value="0">
<input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
</label>
As shown in the forms markup documentation
You will have noticed that the label text is in Italian, the team member who provided localization for Devised worked hard to find out how to do so, and I do not want to force he to work on it again introducing new localized strings.
I am aware of the nice fact that the FormBuidler label method accepts a block as an argument so I could do
<% f.label :remeber_me do %>
<%= f.check_box :remember_me %>
<% end %>
But this produce an HTML output whitout the label! o.O
To be specific this is what I get:
<input name="user[remember_me]" type="hidden" value="0">
<input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
I tried to look in the source code, the f.label method calls the label method, but I can only see that if there is a block no text will be printed and that the label and block will be rendered by the label_tag of the template_object.
Before diving into a source code digging, and a no sleep night, I decided to wait a moment and ask the lifesafer community of StackOverflow for help.
Am I missing something? I am calling f.label with block in the wrong way? Is some parameter missing?
Thanks!!
I don't know if you ever got this working...
Running on Rails 3.2.6 this is what I had to do:
<%= f.label :remember_me do %>
<%= f.check_box :remember_me %>
Remember Me?
<% end %>
I hope that helps you since I came here looking for an answer to the exact same problem and couldn't find it, except through trial and error.
If you want the label and checkbox on the same line, you must include .form-inline in your
<form class="form-inline">
<label for="user_remember_me">Ricordati di me</label>
<input name="user[remember_me]" type="hidden" value="0">
<input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
</form>
http://jsfiddle.net/baptme/66TJY/
<%= form_tag( :class => "form-inline") %>
I have the following code
form.label :artists
which outputs
<label for="artist_artist_name">Artist name</label>
How did rails find the strings artist_artist_name and Artist name?
In general, how can I track this kind of information down?
I have tried grep -ri artists * in the project root but there is no result (apart from form.label :artists). Same for Artist name...
The form helper is used as in the following snippet:
<%= form_for #person do |f| %>
<%= f.label :first_name %>:
<%= f.text_field :first_name %><br />
<%= f.label :last_name %>:
<%= f.text_field :last_name %><br />
<%= f.submit %>
<% end %>
What follows f.label or f.text_field is the identifier of a property for the object referred by #person.
The CSS ID you notice is simply obtained concatenating the name of the variable with an underscore, and the property name; the label is obtained replacing the underscores in the property with spaces, and rewriting the first word in capital case.
The code I reported would generate the following HTML (I removed the parts that were not important).
<form action="/people" class="new_person" id="new_person" method="post">
<label for="person_first_name">First name</label>:
<input id="person_first_name" name="person[first_name]" size="30" type="text" /><br />
<label for="person_last_name">Last name</label>:
<input id="person_last_name" name="person[last_name]" size="30" type="text" /><br />
<input name="commit" type="submit" value="Create Person" />
</form>
How do I change the order of the input element that simple form generate?
Because the hidden checkbox does block for clicking the label.
My simple_form code:
<label>
<span>Company<b></b></span>
<%= f.check_box :company_is_true %>
</label>
The form simple form generate:
<label>
<span>Company<b>0</b></span>
<input type="hidden" value="0" name="search[company_is_true]">
<input type="checkbox" value="1" name="search[company_is_true]" id="search_company_is_true">
</label>
That I want to generate, that works when clicking on label:
<label>
<span>Company<b>0</b></span>
<input type="checkbox" value="1" name="search[company_is_true]" id="search_company_is_true">
<input type="hidden" value="0" name="search[company_is_true]">
</label>
I don't know how to add a comment to the list of comments, but in response to:
The user should be able to click on the label to check and uncheck the checkbox – Rails
beginner 1 hour ago
It's not the checkbox that prevents the user from clicking on that label, it's the lack of the for="" in
<label>
<span>Company<b></b></span>
<%= f.check_box :company_is_true %>
</label>
Either use <%= f.label %> as agmcleod mentioned, or add a for="" to the label:
<label for="search_company_is_true">
<span>Company<b></b></span>
<%= f.check_box :company_is_true %>
</label>
In a traditional html form, it should be structured something like this:
<label for="name">Name: </label>
<input type="text" name="name" />
The for attribute connects it to a field with either a name attribute or id attribute with that value you use in for. To do this in rails, use the following:
<%= f.label :company_is_true, 'Company' %>
<%= f.check_box :company_is_true %>