Keeping your errors in line

How many times has this happened to you? You get a cool design for your website, and you spend a bunch of time lining up all of your images and roundy-corner widgets and input boxes just… so…, and everything looks great. But, then you submit a form without typing in your favorite ice cream (a required field, of course), and suddenly your layout is splattered about like an extra large scoop of rocky road in the hands of a two year old. It’s enough to make you want to stab your eyes out with a hedge trimmer.

The reason is, of course, that ActionView automagically wraps a div around any input element for an ActiveRecord attribute with validation errors. This div has the class ‘fieldWithErrors’, which makes it all red and nasty looking to tell your wayward user that they need to cough up some more information.

Now, input elements are inline elements, so they don’t break page flow. At the same time, div elements are block elements, so they break page flow and use up as much width as is available to them. When ActionView renders a form for your ActiveRecord object with errors, it alters the HTML structure that you’ve so painstakingly laid out, inserting these disruptive divs where previously there were only gentle, friendly input elements. Not to mention that it might be inserting these div elements inside other HTML elements that, according to the standard, mustn’t contain div elements. BOOM. Browser-specific nastiness all over the place.

So, a fellow by the name of Alex MacCaw opened a Rails ticket with a patch to change this fieldWithErrors div element to a span. Span elements are, of course, the inline version of div elements.

Based on some of the feedback, and the fact that ActionView modifying the HTML structure of my views annoys me, I created a somewhat more invasive patch for this ticket.

I changed ActionView to not add an any elements to the HTML structure, but to add the ‘fieldWithErrors’ class directly onto the input element for the attribute with errors.

I also added a #field_error_options class accessor on ActionView::Base, with which you can customize the HTML attributes that ActionView adds to these inputs. The value of #field_error_options defaults to

{ :class => 'fieldWithErrors' }

This will combine with any class option you’ve specified on your tag builder, so

<%= text_field @foo, :bar, :class => 'wibble' %>

will generate

<input type='text' name='foo[bar]' class='fieldWithErrors wibble' />

when the bar field fails validation on @foo.

ActionView::Base still has the #field_error_proc class accessor, so you can still add HTML structure to input elements for invalid attributes if you so choose. However, I changed this to default to nil.

Check it out, see what you think. And keep away from the hedge trimmer.