Rails: Using form_for multiple times (DOM ids) - ruby-on-rails

I would like to use the form_for helper multiple times for the same model in the same page. But the input fields use the same ID attribute (in the HTML), so clicking on the label of a field in another form will select the same input in the first form.
Is there a solution besides settings all attributes manually via :for => "title_#{item.id}" and :id => "title_#{item.id}"?
Using Rails 3.0.9

You can use :namespace => 'some_unique_prefix' option. In contrast to :index, this will not change the value used in the name attribute.
It's also possible to use an array, e.g. when you have nested forms or different forms that happen to have some fields in common: :namespace => [#product.id, tag.id] or :namespace => [:product, #product.id]

I found the answer myself, one can pass a :index option to form_for. That string will be used in the id and for attributes:
<%= form_for #person, :index => #person.id do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
will parse
<form accept-charset="UTF-8" action="/person/11" class="edit_person" id="edit_person_11" method="post">
<!-- Hidden div for csrf removed -->
<label for="person_11_name">Name</label>
<input id="person_11_name" name="person[11][name]" size="30" type="text" />
<input name="commit" type="submit" value="Update Person" />
</form>
Notice it'll change the name of the inputs as well.

I believe you can add this param:
:html => { :id => 'id_i_want' }

Related

Simple_form bootstrap style inline-form not working properly

I have a working twitter bootstrap install and simple form generates the following:
<form accept-charset="UTF-8" action="/find_map" class="simple_form form-inline" id="new_location" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="p5CSoidWaoGMfHY0/3ElWi0XJVg6Cqi9GqWRNlJLBQg=" /></div>
<div class="control-group string required"><div class="controls"><input class="string required" id="location_address" name="location[address]" placeholder="Address" size="50" type="text" /></div></div><input class="btn" name="commit" type="submit" value="Find!" />
</form>
Somehow the "Find!" button won't appear on the same line as the search box. Any ideas?
Thanks!
UPDATE:
Sorry I should have mentioned that all the markup is generated by simple_form based on the following:
<%= simple_form_for #location, :url => find_map_path, :html => { :class => 'form-inline' } do |f| %>
<%= f.input :address, :label => false, :placeholder => "Address" %>
<%= f.submit "Find!", :class => 'btn' %>
<% end %>
So, really, there seems to be an issue with the generated markup, even though I have run the bootstrap install for simple_form, etc.
The above image shows a straight html form
<form class="form-inline">
<input type="text" class="input-small" placeholder="Email">
<button type="submit" class="btn">Sign in</button>
</form>
...above the one generated by simple_form.
I think there are a couple issues here. One is the formatting, and the way simple_form adds a <div> around the input field. #Ron's suggestion of using input_field works for me with simple_form 2.0.1. My example is searching for name in a Contacts table. The following makes the text box and button appear side by side:
<%= simple_form_for :contact, :method => 'get',
:html => { :class => 'form-search' } do |f| %>
<%= f.input_field :search, :placeholder => "Name",
:class => "input-medium search-query" %>
<%= f.submit "Find!", :class => "btn" %>
<% end %>
The other issue is that it seems simple_form usually assumes you want to work with model and field names. The example above uses a :symbol instead of a #model as the first argument as suggested here. But that still generates an input field named contact[search] so you'd have to tell your controller how to deal with that.
I think in this case it may be simpler to not use simple_form and instead use something like the form near the beginning of Ryan Bates' Railscast #240, Search, Sort, Paginate with AJAX:
<%= form_tag contacts_path, :method => 'get', :class => "form-search" do %>
<%= text_field_tag :search, nil, :placeholder => "Name",
:class => "input-medium search-query" %>
<%= submit_tag "Find!", :name => nil, :class => "btn" %>
<% end %>
Now the field is just named "search" and I can consume it in my controller's #index method something like this:
#contacts = #contacts.search(params[:search])
assuming I have this in my model:
def self.search(search)
if search
where('lower(name) LIKE ?', "%#{search.downcase}%")
else
scoped
end
end
It's creating subforms because you're passing input to simple_form. Use input_field instead. (BTW, this also works with simple_fields_for).
You need to customize the control-group and controls div classes to display as inline-block when they are under a form-inline form:
form.form-inline div.control-group { display: inline-block; }
form.form-inline div.control-group div.controls { display: inline-block; }
Adding to Mark's reply:
So, input_field exists to create the input component only, it won't give you any sort of label/error/wrapper. That means you won't get any or tag wrapping the field, you should do that manually in case you want to.
Now about using the form with an object, SimpleForm is a FormBuilder, which means it was created to work with a namespace, either an object or a symbol. SimpleForm's simple_form_for == Rails' form_for, you always need an object namespace to work with.
For such a simple case as a search form, you're better off with simple form helpers such as form_tag, as you've pointed out. There's no need to rely on simple_form_for or form_for for that, I agree and I usually go down that path.
I hope that helps, let me know if you still have doubts.
Change the :html => { :class => 'form-inline' } to :html => { :class => 'form-horizontal' }
can't you move the input button next to input address? I think it will solve the problem
<form accept-charset="UTF-8" action="/find_map" class="simple_form form-inline" id="new_location" method="post" novalidate="novalidate">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="p5CSoidWaoGMfHY0/3ElWi0XJVg6Cqi9GqWRNlJLBQg=" />
</div>
<div class="control-group string required">
<div class="controls">
<input class="string required" id="location_address" name="location[address]" placeholder="Address" size="50" type="text" />
<!-- move the button to here -->
<input class="btn" name="commit" type="submit" value="Find!" />
</div>
</div>
</form>
Please, all people with this problem, don't use fluid layout and be sure you are specifying the HTML5 doctype to the documents.

Cant make form date_select hidden in rails

I am trying to create a form which loads upon a user clicking a date in a calendar, the form then is passed the date that is clicked through the URL and the controller assigns that date to the #date variable. I then create a date_select element and assign it the #date variable. This works fine but since I do not want the user to be able to edit the date in the form I want it to be hidden.
I pass these html options to the form but it doesn't seem to ever effect the HTML:
<%= f.date_select :date, :default => #date, :type => "hidden" %>
Am I missing something? I also tried passing it in an HTML hash :html => { :type = "hidden" } but that doesn't work either. Even when I try something different like :class => "something" it doesn't change the HTML. Is there something special about the date_select helper?
date_select accepts the options discard_day, discard_month and discard_year to do exactly what you are trying to achieve.
<%= f.date_select :date, { :discard_day => true, :discard_month => true, :discard_year => true } %>
Behind the scenes, it generates the following HTML code:
<input id="record_date_3i" name="record[date(3i)]" type="hidden" value="5" />
<input id="record_date_2i" name="record[date(2i)]" type="hidden" value="1" />
<input id="record_date_1i" name="record[date(1i)]" type="hidden" value="2012" />
No CSS tricks, no changes in your controllers.
Per the name, date_select generates <select> elements. In no version of (X)HTML does the select element support the type attribute. If you want a hidden form field then you should use the hidden_field helper, which generates <input type="hidden"> elements.
(To answer your implied question about using e.g. :class => 'something', the problem is that the options and html_arguments parameters must be two separate hashes, but if you do something like this:
<%= f.date_select :date, :default => #date, :class => 'something' %>
..the Ruby interpreter assumes that you have supplied a single hash, i.e. { :default => #date, :class => 'something' } (and really, can you blame it?), and since class isn't a valid key for the options hash it's ignored. Instead you have to make it obvious to Ruby that these are two separate parameters by doing something like this instead:
<%= f.date_select :date, :default => #date, { :class => 'something' } %>
<%# Hey Ruby, this is a different Hash! ----^ %>
See the difference? Of course you could go bonkers and be really obvious, e.g.:
<%= f.date_select(:date, { :default => #date }, { :class => 'something' }) %>
..but that's ugly and egregious so don't bother.)
You can put it inside a hidden div:
<div style="display: none;">
<%= f.date_select :date, :default => #date, :type => "hidden" %>
</div>
That will allow you to have all the fields and hidden you can also use for date and time select:
<div style="display: none;">
<%= f.datetime_select :date, :default => #date, :type => "hidden" %>
</div>

Ruby on rails tag functions. Why does the case of radio_button_tag.id not match label.for?

While registering for openstreetmap, on the terms page, I noticed that clicking the labels didn't check the radio buttons associated with them. Here is the html:
<!-- legale is GB -->
<form action="/user/terms" method="post">
<p>
Please select your country of residence:
<input id="legale_fr" name="legale"
onchange="Element.update("contributorTerms", "<img alt=\"Searching\" src=\"/images/searching.gif?1313181320\" />");; new Ajax.Request('/user/terms?legale=FR', {asynchronous:true, evalScripts:true})"
type="radio" value="FR" />
<label for="legale_FR">France</label>
<input id="legale_it" name="legale" ... type="radio" value="IT" />
<label for="legale_IT">Italy</label>
<input checked="checked"
id="legale_gb" name="legale" ... type="radio" value="GB" />
<label for="legale_GB">Rest of the world</label>
</p>
</form>
As you can see the checkbox id="legale_gb" doesn't match the label for="legale_GB".
Now openstreetmap's website is actually open source so we can read the terms.html.erb:
<!-- legale is <%= #legale %> -->
<% form_tag :action => 'terms' do %>
<p>
<%= t 'user.terms.legale_select' %>
<% [['france', 'FR'], ['italy', 'IT'], ['rest_of_world', 'GB']].each do |name,legale| %>
<%=
radio_button_tag 'legale', legale, #legale == legale,
:onchange => remote_function(
:before => update_page do |page|
page.replace_html 'contributorTerms', image_tag('searching.gif')
end,
:url => {:legale => legale}
)
%>
<%= label_tag "legale_#{legale}", t('user.terms.legale_names.' + name) %>
<% end %>
</p>
<% end %>
I'm a rails newbie, but I can't see anything there that lowercases the id of the radio button tag. What's more, even when I look at the source of radio_button_tag, sanitize_to_id I can't see where this is coming from.
Anyone got any idea what's causing this?
Edit Swapped out label for radio in my description according to answer from
2 things:
Wrong tag, the offender is radio_button_tag (it's capped as expected in the label).
Seems like you're linking to the wrong Rails. According to this project's environment.rb, it's using Rails 2.3.14. If you look at radio_button_tag for that release, you'll see the culprit.
# our pretty tag value is downcased on line 318
pretty_tag_value = value.to_s.gsub(/\s/, "_").gsub(/(?!-)\W/, "").downcase
# although the pretty name is not, oddly
pretty_name = name.to_s.gsub(/\[/, "_").gsub(/\]/, "")
# then the two are combined into the HTML id
html_options = { ..., "id" => "#{pretty_name}_#{pretty_tag_value}", ... }

Get data from html form to ruby in Ruby on Rails

Get data from html form to ruby in Ruby on Rails
I have some html like this
<html>
<h1>Text to PDF</h1>
<textarea name="comments" cols="40" rows="5">
Enter your Text here...
</textarea><br>
<input type="submit" value="Submit" />
</form>
</body>
</html>
I want to give the value of the text into the controller for this page/view.
How do I do this with rails?
I am new to rails, what is the mechanism for this? I don't need to write to the database just want to hand it to the controller. If there is a good tutorial for this sort of thing that would be great, I am not convince I am approaching this correctly.
You can use params['comments'] in your controller to get the value.
In your controller-
def parse_comments
comments_from_form = params['myform']['comments']
#do your stuff with comments_from_form here
end
In your view-
<h1>Text to PDF </h1>
<%= form_tag :action => 'parse_comments' do %>
<%= text_area :myform, :comments, :cols => '40', :rows => '5' %>
<%= submit_tag "Submit" %>
<% end %>
(edit: added = to form_tag opening, without it code won't work)

Simple hidden field in non-model form

What's the simplest way in Ruby-on-Rails to create several simple hidden fields with known values and the same name in a number of non-model forms (form_remote_tag in my case, but I'm guessing that isn't relevant)?
By "simple hidden field", I mean one where the name is just a single string (field_name) rather than part of an array (field_name[]), so that the value can be read simply from the params hash as params[:field_name] rather than params[:field_name][0].
I have found that
<% form_remote_tag :url => {:action => "do_act"} do %>
<%= hidden_field :field_name, 0, :name => "field_name", :value => "foo" %>
<%= submit_tag "Submit" %>
<% end %>
produces an acceptable element (<input id="field_name_0" name="field_name" type="hidden" value="foo" />), but if I omit the :name parameter then the rendered field has the name field_name[0]. Omitting the 0 obviously causes really odd behaviour.
<%= hidden_field_tag :field_name, "foo" %> produces an acceptable element if there's only one such form, but generates HTML warnings (duplicate IDs) if there are more than one.
Is there a way to do this (barring defining a helper) in fewer arguments?
I would use hidden_field_tag and set the ID manually based on some value that is different for each form. Like this:
<%= hidden_field_tag :field_name, 'value', :id => 'field_name_' + unique_value %>
Where unique_value can be anything at all. If these forms have some sort of parent record that they refer to, it could be the ID of the parent. I assume that's why you have multiple similar forms on the same page in the first place.
You can simple pass the ID as an option. The method (form_tag_helper.rb) is defined as:
def hidden_field_tag(name, value = nil, options = {})
text_field_tag(name, value, options.stringify_keys.update("type" => "hidden"))
end
So writing:
<%= hidden_field_tag :field_name, "foo", :id => "hidden_field_1" %>
<%= hidden_field_tag :field_name, "bar", :id => "hidden_field_2" %>
Produces:
<input id="hidden_field_1" name="field_name" type="hidden" value="foo" />
<input id="hidden_field_2" name="field_name" type="hidden" value="bar" />
Try hidden_field_tag:
<%= hidden_field_tag :field_name, "foo" %>

Resources