Twitter Bootstrap FormBuilder

Produce complex Bootstrapped forms with inline errors with minimal typing

View Project on GitHub.comView Gem on RubyGems.org

A simplistic "new post" form:

Never manually render a <label> again!

<% # Uses the TBFB helper to include the form-horizontal class %>
<%= form_for @post do |f| %>

  <% # Generates a control group with both "text_field" and "email" classes %>
  <%= f.text_field :email %>

  <% # Show both the left and right labels %>
  <%= f.check_box :hide_email, :text => "Don't show my email address in my posts" %>

  <% # Show a helpful message %>
  <%= f.text_area :body, :help_block => "Simple HTML tags are allowed", :rows => 3 %>

  <% # Show only the right ":text" label %>
  <%= f.check_box :terms_of_service, :label => nil, :text => "I have read and agreed to the terms of service" %>

  <div class="form-actions">
    <%= f.submit "Create", :primary => true %>
    <a href="/" class="btn">Cancel</a>
  </div>

<% end %>

Simple HTML tags are allowed

The labels and control group markup are generated automatically by a single call

<form accept-charset="UTF-8" action="/posts" class="form-horizontal " id="new_post" method="post">
  <!-- Rails plumbing omitted -->

  <div class=" text_field control-group name">
    <label class="control-label" for="post_name">Name</label>
    <div class="controls">
      <input id="post_name" name="post[name]" size="30" type="text" />
    </div>
  </div>

  <div class=" text_field control-group email">
    <label class="control-label" for="post_email">Email</label>
    <div class="controls">
      <input id="post_email" name="post[email]" size="30" type="text" />
    </div>
  </div>

  <div class="control-group hide_email">
    <label class="control-label" for="post_hide_email">Hide email</label>
    <div class="controls">
      <label class="checkbox" for="post_hide_email">
        <input name="post[hide_email]" type="hidden" value="0" />
        <input id="post_hide_email" name="post[hide_email]" type="checkbox" value="1" />
        Don't show my email address in my posts</label>
    </div>
  </div>

  <div class=" text_field control-group topic">
    <label class="control-label" for="post_topic">Topic</label>
    <div class="controls">
      <input id="post_topic" name="post[topic]" size="30" type="text" />
    </div>
  </div>

  <div class=" text_area control-group body">
    <label class="control-label" for="post_body">Body</label>
    <div class="controls">
      <textarea cols="40" id="post_body" name="post[body]" rows="3">
      </textarea>
      <p class="help-block">Simple HTML tags are allowed</p>
    </div>
  </div>

  <div class="control-group terms_of_service">
    <div class="controls">
      <label class="checkbox" for="post_terms_of_service">
        <input name="post[terms_of_service]" type="hidden" value="0" />
        <input id="post_terms_of_service" name="post[terms_of_service]" type="checkbox" value="1" />I have read and agreed to the terms of service</label>
    </div>
  </div>

  <div class="form-actions">
    <input class=" btn btn-primary" name="commit" type="submit" value="Create" />
    <a href="/" class="btn">Cancel</a>
  </div>

</form>

By default TBFB renders inline error messages and adds error classes to your markup

Name can't be blank
Topic can't be blank

Simple HTML tags are allowed

Body can't be blank
Terms of service must be accepted

The labels and control group markup are generated automatically by a single call.

Note that no attempt has been made to strip out Rails' field_with_error divs that wrap the individual form elements.

<form accept-charset="UTF-8" action="/posts" class="form-horizontal " id="new_post" method="post">

  <!-- Rails plumbing omitted -->

  <div class=" text_field control-group name error">
    <div class="field_with_errors">
      <label class="control-label" for="post_name">Name</label>
    </div>
    <div class="controls">
      <div class="field_with_errors">
        <input id="post_name" name="post[name]" size="30" type="text" value="" />
      </div>
      <span class="help-inline">Name can't be blank</span>
    </div>
  </div>

  <div class=" text_field control-group email error">
    <div class="field_with_errors">
      <label class="control-label" for="post_email">Email</label>
    </div>
    <div class="controls">
      <div class="field_with_errors">
        <input id="post_email" name="post[email]" size="30" type="text" value="" />
      </div>
      <span class="help-inline">Email can't be blank</span>
    </div>
  </div>

  <div class="control-group hide_email">
    <label class="control-label" for="post_hide_email">Hide email</label>
    <div class="controls">
      <label class="checkbox" for="post_hide_email">
        <input name="post[hide_email]" type="hidden" value="0" />
        <input id="post_hide_email" name="post[hide_email]" type="checkbox" value="1" /> Don't show my email address in my posts</label>
    </div>
  </div>

  <div class=" text_field control-group topic error">
    <div class="field_with_errors">
      <label class="control-label" for="post_topic">Topic</label>
    </div>
    <div class="controls">
      <div class="field_with_errors">
        <input id="post_topic" name="post[topic]" size="30" type="text" value="" />
      </div>
      <span class="help-inline">Topic can't be blank</span>
    </div>
  </div>

  <div class=" text_area control-group body error">
    <div class="field_with_errors">
      <label class="control-label" for="post_body">Body</label>
    </div>
    <div class="controls">
      <div class="field_with_errors">
        <textarea cols="40" id="post_body" name="post[body]" rows="3">
        </textarea>
      </div>
      <p class="help-block">Simple HTML tags are allowed</p>
      <span class="help-inline">Body can't be blank</span>
    </div>
  </div>

  <div class="control-group terms_of_service error">
    <div class="controls">
      <label class="checkbox" for="post_terms_of_service">
        <input name="post[terms_of_service]" type="hidden" value="0" />
        <div class="field_with_errors">
          <input id="post_terms_of_service" name="post[terms_of_service]" type="checkbox" value="1" />
      </div> I have read and agreed to the terms of service</label>
      <span class="help-inline">Terms of service must be accepted</span>
    </div>
  </div>

  <div class="form-actions">
    <input class=" btn btn-primary" name="commit" type="submit" value="Create" />
    <a href="/" class="btn">Cancel</a>
  </div>

</form>

Get the Gem

Add the Gem to your Gemfile:

gem twitter-bootstrap-form-builder

or install it manually:

gem install twitter-bootstrap-form-builder

Add the Helper

The Gem includes a helper which overrides form_for, automatically setting the :builder option and adding Twitter Bootstrap's clases to your <form> tag.

Include MNE::TwitterBootstrapFormBuilder::Helper in your ApplicationHelper module:

# app/helpers/application_helper.rb

module ApplicationHelper
  include MNE::TwitterBootstrapFormBuilder::Helper

  # Your helpers here...

    end

Assuming you've added the helper, use form_for to begin rendering your form, excluding label tags.

<%= form_for @post do |f| %>
  <%= f.text_field :topic %>
<% end %>

A couple of nice things have been done for us based on this one line:

<form accept-charset="UTF-8" action="/posts" class="form-horizontal " id="new_post" method="post">
  <!-- Rails plumbing omitted -->

  <div class="text_field control-group topic">
    <label class="control-label" for="post_topic">Topic</label>
    <div class="controls">
      <input id="post_topic" name="post[topic]" size="30" type="text" />
    </div>
  </div>

</form>

Overriding the Label

Use a string for a custom label:

<%= f.text_field :topic, :label => "Subject" %>
<div class="text_field control-group topic">
  <label class="control-label" for="post_topic">Subject</label>
  <div class="controls">
    <input id="post_topic" name="post[topic]" size="30" type="text" />
  </div>
</div>

Use an array to fully override the arguments to label_tag:

<%= f.text_field :topic, :label => ["My Label", { :class => "extra-bold control-label" }] %>
<div class="text_field control-group topic">
  <label class="extra-bold control-label" for="post_topic">My Label</label>
  <div class="controls">
    <input id="post_topic" name="post[topic]" size="30" type="text" />
  </div>
</div>

Suppressing TwitterBootstrapFormBuilder entirely

If you have some crazy field that requires a ton of markup, use :label => false:

<%= f.text_field :topic, :label => false %>

Exactly like calling regular FormBuilder#text_field:

<input id="post_topic" name="post[topic]" size="30" type="text" />

See the README for documentation, examples and known issues.