
On a recent project, we decided it would be nice to have “templated attributes” for certain fields in a form. A templated attribute has a helpful initial value—kind of like a default value—except that these aren’t valid data or saved in the database. They’re suggestions to the user about the expected formatting or content of a field.
So the game is:
- keep these values out of the database
- specify these values once in the model, super-duper-DRY
- create a user experience that clearly implies that these values are just templates for valid data
Case one: a website attribute
We wanted a website attribute to be prefilled with http:// as a suggestion to the user about proper URL formatting—most users will just enter “example.com” when prompted for a URL. This is to avoid XSS problems with javascript: URIs and the like, and to keep browsers from resolving short URLs to be internal—nothing quite like being sent to http://yoursite.com/www.theirsite.com.
(Aside: there are better ways to handle this specific situation: a :before_validation callback to fix invalid URLs and check for XSS attacks, or the fantastic white_list plugin. But for now I’m interested in the general case.)
This attribute needed certain behavior:
- When the user hits the form, the field should be pre-filled with
http://if the real value is empty or nil. - If the field is left as
http://, we should convert it to nil before validation. - Client-side: to imply that the initial value is a suggestion, we’ll make the text color gray until the user makes a change. If the user’s only change is to empty the field, we should reset it to
http://and gray again on blur.
Case two: label attributes
There’s another use case, which you’ve seen before: a text field’s initial value is used as a replacement for its label. When the user clicks in the field, the “label” disappears. My example of this is a phone attribute, where we’d like to suggest a standard US area code format. Something like (123) 555-1234.
We don’t want the user to have to delete our dummy numbers and put in their own; it’s too much work. Instead we think that the reminder will help coax the right format out of the user by itself—so this field gets blanked on focus, unlike the website attribute.
You also see this pattern used for content suggestions instead of formatting hints: for example, search fields and login forms which are space-constrained, like the built-in search in Firefox and Safari.
Get on with the plugin, already
OK, OK. So we have two kinds of templated attributes: those with starting values, which are potentially the start of valid data, and labels, which are just helpful, ephemeral reminders.
Check out the goods:
1 2 3 4 |
class User < ActiveRecord::Base templated_attribute :website, :starting_value => 'http://' templated_attribute :phone, :label => '(123) 555-1234' end |
Validations work as expected, since unchanged template values get removed in a :before_validation callback. So you can sprinkle on a little :validates_presence_of and :validates_format_of for a really good time.
There’s also some nice, unobtrusive Javascript you can generate to get the behavior I mentioned above. If you’re using form_for, it’s totally automatic. It gets installed when you install the plugin, or you can install and remove manually with these rake tasks:
1 2 |
rake templated_attribute:install rake templated_attribute:remove |
To turn off the Javascript for a given templated_attribute—say, because the generated stuff doesn’t jibe with your fancy-pantsy, AJAX-validating, Grey Poupon of a form—just throw :templated_javascript => false in the options hash for text_field or text_area. You’ll have to do any styling and event handling by yourself.
I’d like to make this work for fields other than text_field and text_area; the other contenders were file_field, which we can’t do because the Javascript security model doesn’t let us touch its value at runtime, and password_field, which I haven’t done because showing the template value would require dynamically switching the element to a text_field and back (to avoid all those asterisks). That one’s on the list, though.
Plugin resources
- Browse the code:
http://railsplugins.code.shiftcommathree.com/browser/templated_attribute - Generated rdocs (with installation instructions):
http://docs.shiftcommathree.com/rails_plugins/templated_attribute - Raw svn action:
https://svn.shiftcommathree.com/rails_plugins/templated_attribute - Feed for svn changesets:
http://railsplugins.code.shiftcommathree.com/changesets.atom

Subscribe to