158

My question is similar to this one but for a Rails app.

I have a form with some radio buttons, and would like to associate labels with them. The label form helper only takes a form field as a parameter, but in this case I have multiple radio buttons for a single form field. The only way I see to do it is to manually create a label, hard coding the ID that is auto generated for the radio button. Does anyone know of a better way to do it?

For example:

<% form_for(@message) do |f| %>
    <%= label :contactmethod %>
    <%= f.radio_button :contactmethod, 'email', :checked => true %> Email
    <%= f.radio_button :contactmethod, 'sms' %> SMS
<% end %>

This generates something like:

<label for="message_contactmethod">Contactmethod</label>
<input checked="checked" id="message_contactmethod_email" name="message[contactmethod]" value="email" type="radio"> Email
<input id="message_contactmethod_sms" name="message[contactmethod]" value="sms" type="radio"> SMS

What I want:

<input checked="checked" id="message_contactmethod_email" name="message[contactmethod]" value="email" type="radio"><label for="message_contactmethod_email">Email</label>
<input id="message_contactmethod_sms" name="message[contactmethod]" value="sms" type="radio"> <label for="message_contactmethod_sms">SMS</label>
0

5 Answers 5

252

Passing the :value option to f.label will ensure the label tag's for attribute is the same as the id of the corresponding radio_button

<%= form_for(@message) do |f| %>
  <%= f.radio_button :contactmethod, 'email' %> 
  <%= f.label :contactmethod, 'Email', :value => 'email' %>
  <%= f.radio_button :contactmethod, 'sms' %>
  <%= f.label :contactmethod, 'SMS', :value => 'sms' %>
<% end %>

See ActionView::Helpers::FormHelper#label

the :value option, which is designed to target labels for radio_button tags

Sign up to request clarification or add additional context in comments.

2 Comments

well, this may have 0 votes because it was answered months later, but actually it's the good one. Caveat: you need Rails >= 2.3.3
this method also renders the field_with_errors div when necessary (that doesn't show up when using the :contactmethod_email method). this is the correct answer!
154
<% form_for(@message) do |f| %>
  <%= f.radio_button :contactmethod, 'email', :checked => true %> 
  <%= label :contactmethod_email, 'Email' %>
  <%= f.radio_button :contactmethod, 'sms' %>
  <%= label :contactmethod_sms, 'SMS' %>
<% end %>

4 Comments

There is another way, too: passing a :value option to f.label will do the same thing. e.g. <%= f.label :contactmethod, 'SMS', :value => 'sms' %>. This sets the "for" attribute of the label tag correctly, which makes clicking the label select the appropriate radio button. In the answer above, simply using the label helper will cause the "for" attribute to be incorrect when the radio button is created with FormBuilder
I just wanted to say that as a newcomer to Rails, I've found this answer the one I keep coming back to. It's the gift that keeps on giving. Well, until I remember the proper syntax anyway... :)
also check this if you are looking for setting the checked value conditionally stackoverflow.com/a/4708921/429521
For future readers, John Douthat has the correct answer to this question. This answer is no longer correct.
1

If you want the object_name prefixed to any ID you should call form helpers on the form object:

- form_for(@message) do |f|
  = f.label :email

This also makes sure any submitted data is stored in memory should there be any validation errors etc.

If you can't call the form helper method on the form object, for example if you're using a tag helper (radio_button_tag etc.) you can interpolate the name using:

= radio_button_tag "#{f.object_name}[email]", @message.email

In this case you'd need to specify the value manually to preserve any submissions.

Comments

1

This an example from my project for rating using radio buttons and its labels

<div class="rating">
  <%= form.radio_button :star, '1' %>
  <%= form.label :star, '☆', value: '1' %>

  <%= form.radio_button :star, '2' %>
  <%= form.label :star, '☆', value: '2' %>

  <%= form.radio_button :star, '3' %>
  <%= form.label :star, '☆', value: '3' %>

  <%= form.radio_button :star, '4' %>
  <%= form.label :star, '☆', value: '4' %>

  <%= form.radio_button :star, '5' %>
  <%= form.label :star, '☆', value: '5' %>
</div>

Comments

0

Using true/false as the value will have the field pre-filled if the model passed to the form has this attribute already filled:

= f.radio_button(:public?, true)
= f.label(:public?, "yes", value: true)
= f.radio_button(:public?, false)
= f.label(:public?, "no", value: false)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.