Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

171 lines (115 sloc) 7.097 kb

Formtastic Sneaky Preview

Formtastic is a Rails FormBuilder DSL (with some other goodies) to make it far easier to create beautiful, semantically rich, syntactically awesome, readily stylable and wonderfully accessible HTML forms in your Rails applications.

The Story

Hacked together forms were easy, but awesome forms with decent semantics, rich mark-up and plenty of CSS hooks were incredibly painful. I was discouraged from doing things properly because it was do much mark-up and code to write. One day, I finally had enough, so I opened up my text editor, and wrote a DSL for how I’d like to author forms:

<% semantic_form_for @article do |form| %>
  
  <%= form.error_messages %>
  
  <% form.input_field_set "Basic" do %>
    <%= form.input :title %>                               
    <%= form.input :body, :rows => 20 %>                                
    <%= form.input :section_id, :include_blank => true %>                          
    <%= form.input :publication_state_id, :as => :radio %> 
    <%= form.input :author_id, :as => :select %>                           
    <%= form.input :allow_comments, :label => "Allow commenting on this article" %>                      
  <% end %>                                                
  
  <% form.input_field_set "Extra" do %>
    <%= form.input :keywords, :required => false, :hint => "Example: ruby, rails, forms" %>        
    <%= form.input :extract, :required => false, :rows => 5 %>
    <%= form.input :description, :required => false, :rows => 5 %>
    <%= form.input :url_title, :required => false %>                           
  <% end %>

  <% form.button_field_set do %>                                    
    <%= form.cancel_button %>                             
    <%= form.commit_button %>                             
  <% end %>

<% end %>

I also wrote the accompanying HTML output I expected, favoring something very similar to the fieldsets, lists and other semantic elements Aaron Gustafson presented in Learning to Love Forms <http://www.slideshare.net/AaronGustafson/learning-to-love-forms-web-directions-south-07>, and then hacked together enough Ruby to prove it could be done.

Configuration

If you wish, put something like this in config/initializers/formtastic_config.rb:

JustinFrench::Formtastic::SemanticFormBuilder.all_fields_required_by_default = false
JustinFrench::Formtastic::SemanticFormBuilder.required_string = "(required)"
JustinFrench::Formtastic::SemanticFormBuilder.optional_string = "(optional)"

Guiding Principals

  • great forms are at the heart of most web applications
  • semantically rich (and far more accessible) HTML forms really are possible with the use of appropriate elements like fieldsets & lists
  • sometimes more mark-up is better
  • stylesheet authors have more options and more control if plenty of structural mark-up, class names and element ids are provided
  • it should be easy to write a great form rather than a crappy form
  • I’m sick of re-inventing the wheel every time I need a form
  • applications with great data modelling and a RESTful architecture are my main consideration
  • there’s no such thing as a silver bullet and I’ll still have to hard-code some things I do
  • best practices and common patterns have to start somewhere

Status

THIS IS DEFINITELY NOT PRODUCTION-READY. THINGS ARE GOING TO CHANGE A LOT.

It’s incredibly opinionated, incomplete, a work in progress, messy around the edges, messy in the middle too, tightly coupled to the database, tightly coupled to “my way” of doing things and also incredibly lacking in unit tests so far, but I hope you try it and offer some suggestions and improvements any way.

Roadmap

  • There’s plenty of TODOs in the code
  • get the basic form_for implementation complete, proven and well tested (did I mention how laborious testing form builders is?)
  • provide generic, reusable, stylesheets that prove this stuff works
  • go back and ensure it works for remote_form_for, etc
  • probably do a shortcut like <%= form.inputs :name, :login, :email, :bio %> for those that want the form with zero configuration

Usage

The smallest example:

<% semantic_form_for @user do |form| %>
  <% form.input_field_set do %>
    <%= form.input :name %>
    <%= form.input :email %>
  <% end %>
<% end %>

With an output something like:

<form id="new-article-form" action="#" method="post">
  <fieldset>
    <legend><span>Create a new User</span></legend>
    <fieldset class="inputs">
      <ol>
        <li id="user_name_input" class="required string">
          <label for="user_name">Name <abbr title="required">*</abbr></label>
          <input type="text" id="user_name" name="user[name]" size="50" />
        </li>
        <li id="user_email_input" class="required string">
          <label for="user_email">Email <abbr title="required">*</abbr></label>
          <input type="text" id="user_email" name="user[email]" size="50" />
        </li>
      </ol>
    </fieldset>
  </fieldset>
</form>

Conventions & Prerequisites

In a few places (like radio or select widgets for belongs_to associations) Formtastic expects your ActiveRecord instances to respond to the to_label method (returning a String). You can easily add this to your models, for example, a User object might want to return the user’s first name, last name and login:

class User < ActiveRecord::Base
  #...
  def to_label
    "#{first_name} #{last_name} (#{login})"
  end
end

What about Stylesheets?

A proof-of-concept (very much a work-in-progress) stylesheet is provided which you can include in your layout. Customisation is best achieved by overriding these styles in an additional stylesheet so that the formtastic styles can be updated without clobbering your changes.

1. Use the generator to copy the formtastic.css into your public directory

./script/generate formtastic_stylesheets

2. Create an empty file public/stylesheets/formtastic_changes.css for your custom styles

3. Add both YUI’s reset.css, formtastic.css and formtastic_changes.css to your layout:

<%= stylesheet_link_tag "http://yui.yahooapis.com/2.5.1/build/reset/reset-min.css" %>
<%= stylesheet_link_tag "formtastic" %>
<%= stylesheet_link_tag "formtastic_changes" %>

Compatibility

I’m only testing Formtastic with the latest Rails stable release.

But it doesn’t do that thing I really need!

Oh noes! It might not ever do it either. We’ll see. This is not a silver bullet. I want to make the usual stuff easy, and the unusual stuff possible. That might mean that some of the inputs on your form still have to be hard-coded, but some is better than all, right?

I really hope the plugin will soon be clean and extensible enough to invite others to contribute more complex input types (calendars, etc) to the core.

Copyright © 2007 Justin French, released under the MIT license.

Jump to Line
Something went wrong with that request. Please try again.