Introducing label_with_index: a simple rails plugin

Posted by jeff

The problem

A while back Rails introduced the label helper, so you can can easily add labels to forms like so:

1
2
<%= label :user, :name %>
# => <label for="user_2_name">Name</label>

Unfortunately the person who committed that change neglected to add support for the auto index and :index options. For example, take the following code snippet:

1
2
<%= text_field :user, :name, :index => 1%>
# => <input id="user_1_name" name="user[1][name]" size="30" type="text" />

Following the principle of least surprise, you might assume that labels would work the same way, but they don’t:

1
2
<%= label :user, :name, nil, :index => 1%>
# => <label for="user_name" index="1">Name</label>

The fix

I’ve just released a plugin called label_with_index that fixes this. Now label helpers take advantage of the autoindex feature and :index keys as you would expect:

1
2
<%= label :user, :name, nil, :index => 1%>
# => <label for="user_1_name">Name</label>

Fixing radio button ids

Rails has also had a bug for quite some time where it will by default emit radio button ids that will fail XHTML validation. To boot, they even advertise this in the docs. Here’s what’s written on http://api.rubyonrails.com/classes/ActionView/Helpers/FormHelper.html :

1
2
3
4
5
# Let's say that @post.category returns "rails":
radio_button("post", "category", "rails")
radio_button("post", "category", "java")
# => <input type="radio" id="post_category" name="post[category]" value="rails" checked="checked" />
#    <input type="radio" id="post_category" name="post[category]" value="java" />

See how those two radio buttons have the same id? Not only will that fail validation, but it can cause unexpected javascript behavior and will cause very odd label-clicking results (clicking the label will most likely highlight the first radio button, regardless of which label is clicked).

label_with_index also fixes this in two ways:

  • Makes the id unique (or at least, as unique as the option is)
  • Adds a :value option to the label helper that can match the radio button’s value

Before:

1
2
3
4
radio_button("post", "category", "java")
label("post", "category")
 # => <input type="radio" id="post_category" name="post[category]" value="java" />
 # => <label for="post_category">Category</label>

After:

1
2
3
4
radio_button("post", "category", "java")
label("post", "category", nil, :value => "java")
 # => <input type="radio" id="post_category_java" name="post[category]" value="java" />
 # => <label for="post_category_java">Category</label>

So with this plugin the rails label helper, and the radio_button helper have support for creating valid ids out of the box.

Installation

git clone git://github.com/zilkey/label_with_index.git vendor/plugins/label_with_index

See the rdoc at http://label_with_index.zilkey.com/

To Do

  • Create a fork of rails on github and add this to core with tests

References

Notes:

It appears that the radio button id may have been fixed on edge rails – I haven’t tested it out fully and I’m not sure if all of the svn patches are synced up on github, so I’ll wait until things settle a bit and make changes as necessary.

Comments

Leave a response

Comment