Class Formtastic::SemanticFormBuilder
In: lib/formtastic.rb
Parent: ActionView::Helpers::FormBuilder

Methods

Constants

RESERVED_COLUMNS = [:created_at, :updated_at, :created_on, :updated_on, :lock_version, :version]
INLINE_ERROR_TYPES = [:sentence, :list, :first]

External Aliases

inline_errors_for -> errors_on

Attributes

template  [RW] 

Public Instance methods

Creates a fieldset and ol tag wrapping for form buttons / actions as list items. See inputs documentation for a full example. The fieldset‘s default class attriute is set to "buttons".

See inputs for html attributes and special options.

Creates a submit input tag with the value "Save [model name]" (for existing records) or "Create [model name]" (for new records) by default:

  <%= form.commit_button %> => <input name="commit" type="submit" value="Save Post" />

The value of the button text can be overridden:

 <%= form.commit_button "Go" %> => <input name="commit" type="submit" value="Go" class="{create|update|submit}" />
 <%= form.commit_button :label => "Go" %> => <input name="commit" type="submit" value="Go" class="{create|update|submit}" />

And you can pass html atributes down to the input, with or without the button text:

 <%= form.commit_button :button_html => { :class => "pretty" } %> => <input name="commit" type="submit" value="Save Post" class="pretty {create|update|submit}" />

Returns a suitable form input for the given method, using the database column information and other factors (like the method name) to figure out what you probably want.

Options:

  • :as - override the input type (eg force a :string to render as a :password field)
  • :label - use something other than the method name as the label text, when false no label is printed
  • :required - specify if the column is required (true) or not (false)
  • :hint - provide some text to hint or help the user provide the correct information for a field
  • :input_html - provide options that will be passed down to the generated input
  • :wrapper_html - provide options that will be passed down to the li wrapper

Input Types:

Most inputs map directly to one of ActiveRecord‘s column types by default (eg string_input), but there are a few special cases and some simplification (:integer, :float and :decimal columns all map to a single numeric_input, for example).

  • :select (a select menu for associations) - default to association names
  • :check_boxes (a set of check_box inputs for associations) - alternative to :select has_many and has_and_belongs_to_many associations
  • :radio (a set of radio inputs for associations) - alternative to :select belongs_to associations
  • :time_zone (a select menu with time zones)
  • :password (a password input) - default for :string column types with ‘password’ in the method name
  • :text (a textarea) - default for :text column types
  • :date (a date select) - default for :date column types
  • :datetime (a date and time select) - default for :datetime and :timestamp column types
  • :time (a time select) - default for :time column types
  • :boolean (a checkbox) - default for :boolean column types (you can also have booleans as :select and :radio)
  • :string (a text field) - default for :string column types
  • :numeric (a text field, like string) - default for :integer, :float and :decimal column types
  • :email (an email input) - default for :string column types with ‘email’ as the method name.
  • :url (a url input) - default for :string column types with ‘url’ as the method name.
  • :phone (a tel input) - default for :string column types with ‘phone’ or ‘fax’ in the method name.
  • :search (a search input) - default for :string column types with ‘search’ as the method name.
  • :country (a select menu of country names) - requires a country_select plugin to be installed
  • :email (an email input) - New in HTML5 - needs to be explicitly provided with :as => :email
  • :url (a url input) - New in HTML5 - needs to be explicitly provided with :as => :url
  • :phone (a tel input) - New in HTML5 - needs to be explicitly provided with :as => :phone
  • :search (a search input) - New in HTML5 - needs to be explicity provided with :as => :search
  • :country (a select menu of country names) - requires a country_select plugin to be installed
  • :hidden (a hidden field) - creates a hidden field (added for compatibility)

Example:

  <% semantic_form_for @employee do |form| %>
    <% form.inputs do -%>
      <%= form.input :name, :label => "Full Name" %>
      <%= form.input :manager, :as => :radio %>
      <%= form.input :secret, :as => :password, :input_html => { :value => "xxxx" } %>
      <%= form.input :hired_at, :as => :date, :label => "Date Hired" %>
      <%= form.input :phone, :required => false, :hint => "Eg: +1 555 1234" %>
      <%= form.input :email %>
      <%= form.input :website, :as => :url, :hint => "You may wish to omit the http://" %>
    <% end %>
  <% end %>

Creates an input fieldset and ol tag wrapping for use around a set of inputs. It can be called either with a block (in which you can do the usual Rails form stuff, HTML, ERB, etc), or with a list of fields. These two examples are functionally equivalent:

  # With a block:
  <% semantic_form_for @post do |form| %>
    <% form.inputs do %>
      <%= form.input :title %>
      <%= form.input :body %>
    <% end %>
  <% end %>

  # With a list of fields:
  <% semantic_form_for @post do |form| %>
    <%= form.inputs :title, :body %>
  <% end %>

  # Output:
  <form ...>
    <fieldset class="inputs">
      <ol>
        <li class="string">...</li>
        <li class="text">...</li>
      </ol>
    </fieldset>
  </form>

Quick Forms

When called without a block or a field list, an input is rendered for each column in the model‘s database table, just like Rails’ scaffolding. You‘ll obviously want more control than this in a production application, but it‘s a great way to get started, then come back later to customise the form with a field list or a block of inputs. Example:

  <% semantic_form_for @post do |form| %>
    <%= form.inputs %>
  <% end %>

  With a few arguments:
  <% semantic_form_for @post do |form| %>
    <%= form.inputs "Post details", :title, :body %>
  <% end %>

Options

All options (with the exception of :name/:title) are passed down to the fieldset as HTML attributes (id, class, style, etc). If provided, the :name/:title option is passed into a legend tag inside the fieldset.

  # With a block:
  <% semantic_form_for @post do |form| %>
    <% form.inputs :name => "Create a new post", :style => "border:1px;" do %>
      ...
    <% end %>
  <% end %>

  # With a list (the options must come after the field list):
  <% semantic_form_for @post do |form| %>
    <%= form.inputs :title, :body, :name => "Create a new post", :style => "border:1px;" %>
  <% end %>

  # ...or the equivalent:
  <% semantic_form_for @post do |form| %>
    <%= form.inputs "Create a new post", :title, :body, :style => "border:1px;" %>
  <% end %>

It‘s basically a fieldset!

Instead of hard-coding fieldsets & legends into your form to logically group related fields, use inputs:

  <% semantic_form_for @post do |f| %>
    <% f.inputs do %>
      <%= f.input :title %>
      <%= f.input :body %>
    <% end %>
    <% f.inputs :name => "Advanced", :id => "advanced" do %>
      <%= f.input :created_at %>
      <%= f.input :user_id, :label => "Author" %>
    <% end %>
    <% f.inputs "Extra" do %>
      <%= f.input :update_at %>
    <% end %>
  <% end %>

  # Output:
  <form ...>
    <fieldset class="inputs">
      <ol>
        <li class="string">...</li>
        <li class="text">...</li>
      </ol>
    </fieldset>
    <fieldset class="inputs" id="advanced">
      <legend><span>Advanced</span></legend>
      <ol>
        <li class="datetime">...</li>
        <li class="select">...</li>
      </ol>
    </fieldset>
    <fieldset class="inputs">
      <legend><span>Extra</span></legend>
      <ol>
        <li class="datetime">...</li>
      </ol>
    </fieldset>
  </form>

Nested attributes

As in Rails, you can use semantic_fields_for to nest attributes:

  <% semantic_form_for @post do |form| %>
    <%= form.inputs :title, :body %>

    <% form.semantic_fields_for :author, @bob do |author_form| %>
      <% author_form.inputs do %>
        <%= author_form.input :first_name, :required => false %>
        <%= author_form.input :last_name %>
      <% end %>
    <% end %>
  <% end %>

But this does not look formtastic! This is equivalent:

  <% semantic_form_for @post do |form| %>
    <%= form.inputs :title, :body %>
    <% form.inputs :for => [ :author, @bob ] do |author_form| %>
      <%= author_form.input :first_name, :required => false %>
      <%= author_form.input :last_name %>
    <% end %>
  <% end %>

And if you don‘t need to give options to your input call, you could do it in just one line:

  <% semantic_form_for @post do |form| %>
    <%= form.inputs :title, :body %>
    <%= form.inputs :first_name, :last_name, :for => @bob %>
  <% end %>

Just remember that calling inputs generates a new fieldset to wrap your inputs. If you have two separate models, but, semantically, on the page they are part of the same fieldset, you should use semantic_fields_for instead (just as you would do with Rails’ form builder).

Generates the label for the input. It also accepts the same arguments as Rails label method. It has three options that are not supported by Rails label method:

  • :required - Appends an abbr tag if :required is true
  • :label - An alternative form to give the label content. Whenever label
             is false, a blank string is returned.
    
  • :input_name - Gives the input to match for. This is needed when you want to
                  to call f.label :authors but it should match :author_ids.
    

Examples

 f.label :title # like in rails, except that it searches the label on I18n API too

 f.label :title, "Your post title"
 f.label :title, :label => "Your post title" # Added for formtastic API

 f.label :title, :required => true # Returns <label>Title<abbr title="required">*</abbr></label>

Generates error messages for given method names and for base. You can pass a hash with html options that will be added to ul tag

Examples

 f.semantic_errors # This will show only errors on base
 f.semantic_errors :state # This will show errors on base and state
 f.semantic_errors :state, :class => "awesome" # errors will be rendered in ul.awesome

A thin wrapper around fields_for to set :builder => Formtastic::SemanticFormBuilder for nesting forms:

  # Example:
  <% semantic_form_for @post do |post| %>
    <% post.semantic_fields_for :author do |author| %>
      <% author.inputs :name %>
    <% end %>
  <% end %>

  # Output:
  <form ...>
    <fieldset class="inputs">
      <ol>
        <li class="string"><input type='text' name='post[author][name]' id='post_author_name' /></li>
      </ol>
    </fieldset>
  </form>

Protected Instance methods

Outputs a label containing a checkbox and the label text. The label defaults to the column name (method name) and can be altered with the :label option. :checked_value and :unchecked_value options are also available.

Outputs a fieldset containing a legend for the label text, and an ordered list (ol) of list items, one for each possible choice in the belongs_to association. Each li contains a label and a check_box input.

This is an alternative for has many and has and belongs to many associations.

Example:

  f.input :author, :as => :check_boxes

Output:

  <fieldset>
    <legend class="label"><label>Authors</label></legend>
    <ol>
      <li>
        <input type="hidden" name="book[author_id][1]" value="">
        <label for="book_author_id_1"><input id="book_author_id_1" name="book[author_id][1]" type="checkbox" value="1" /> Justin French</label>
      </li>
      <li>
        <input type="hidden" name="book[author_id][2]" value="">
        <label for="book_author_id_2"><input id="book_author_id_2" name="book[owner_id][2]" type="checkbox" value="2" /> Kate French</label>
      </li>
    </ol>
  </fieldset>

Notice that the value of the checkbox is the same as the id and the hidden field has empty value. You can override the hidden field value using the unchecked_value option.

You can customize the options available in the set by passing in a collection (Array) of ActiveRecord objects through the :collection option. If not provided, the choices are found by inferring the parent‘s class name from the method name and simply calling all on it (Author.all in the example above).

Examples:

  f.input :author, :as => :check_boxes, :collection => @authors
  f.input :author, :as => :check_boxes, :collection => Author.all
  f.input :author, :as => :check_boxes, :collection => [@justin, @kate]

The :label_method option allows you to customize the label for each checkbox two ways:

  • by naming the correct method to call on each object in the collection as a symbol (:name, :login, etc)
  • by passing a Proc that will be called on each object in the collection, allowing you to use helpers or multiple model attributes together

Examples:

  f.input :author, :as => :check_boxes, :label_method => :full_name
  f.input :author, :as => :check_boxes, :label_method => :login
  f.input :author, :as => :check_boxes, :label_method => :full_name_with_post_count
  f.input :author, :as => :check_boxes, :label_method => Proc.new { |a| "#{a.name} (#{pluralize("post", a.posts.count)})" }

The :value_method option provides the same customization of the value attribute of each checkbox input tag.

Examples:

  f.input :author, :as => :check_boxes, :value_method => :full_name
  f.input :author, :as => :check_boxes, :value_method => :login
  f.input :author, :as => :check_boxes, :value_method => Proc.new { |a| "author_#{a.login}" }

Formtastic works around a bug in rails handling of check box collections by not generating the hidden fields for state checking of the checkboxes The :hidden_fields option provides a way to re-enable these hidden inputs by setting it to true.

  f.input :authors, :as => :check_boxes, :hidden_fields => false
  f.input :authors, :as => :check_boxes, :hidden_fields => true

Finally, you can set :value_as_class => true if you want the li wrapper around each checkbox / label combination to contain a class with the value of the radio button (useful for applying specific CSS or Javascript to a particular checkbox).

Outputs a country select input, wrapping around a regular country_select helper. Rails doesn‘t come with a country_select helper by default any more, so you‘ll need to install the "official" plugin, or, if you wish, any other country_select plugin that behaves in the same way.

The Rails plugin iso-3166-country-select plugin can be found "here":github.com/rails/iso-3166-country-select.

By default, Formtastic includes a handfull of english-speaking countries as "priority counties", which you can change to suit your market and user base (see README for more info on config).

Examples:

  f.input :location, :as => :country # use Formtastic::SemanticFormBuilder.priority_countries array for the priority countries
  f.input :location, :as => :country, :priority_countries => /Australia/ # set your own

Outputs a fieldset with a legend for the method label, and a ordered list (ol) of list items (li), one for each fragment for the date (year, month, day). Each li contains a label (eg "Year") and a select box. Overwriting the label is possible by adding the :labels option. :labels should be a hash with the field (e.g. day) as key and the label text as value. See date_or_datetime_input for a more detailed output example.

Some of Rails’ options for select_date are supported, but not everything yet, see documentation of date_or_datetime_input() for more information.

Helper method used by :as => (:date|:datetime|:time). Generates a fieldset containing a legend (for what would normally be considered the label), and an ordered list of list items for year, month, day, hour, etc, each containing a label and a select. Example:

<fieldset>

  <legend>Created At</legend>
  <ol>
    <li>
      <label for="user_created_at_1i">Year</label>
      <select id="user_created_at_1i" name="user[created_at(1i)]">
        <option value="2003">2003</option>
        ...
        <option value="2013">2013</option>
      </select>
    </li>
    <li>
      <label for="user_created_at_2i">Month</label>
      <select id="user_created_at_2i" name="user[created_at(2i)]">
        <option value="1">January</option>
        ...
        <option value="12">December</option>
      </select>
    </li>
    <li>
      <label for="user_created_at_3i">Day</label>
      <select id="user_created_at_3i" name="user[created_at(3i)]">
        <option value="1">1</option>
        ...
        <option value="31">31</option>
      </select>
    </li>
  </ol>

</fieldset>

This is an absolute abomination, but so is the official Rails select_date().

Options:

  * @:order => [:month, :day, :year]@
  * @:include_seconds@ => true@
  * @:discard_(year|month|day|hour|minute) => true@
  * @:include_blank => true@
  * @:labels => {}@

Outputs a fieldset with a legend for the method label, and a ordered list (ol) of list items (li), one for each fragment for the date (year, month, day, hour, min, sec). Each li contains a label (eg "Year") and a select box. Overwriting the label is possible by adding the :labels option. :labels should be a hash with the field (e.g. day) as key and the label text as value. See date_or_datetime_input for a more detailed output example.

Some of Rails’ options for select_date are supported, but not everything yet, see documentation of date_or_datetime_input() for more information.

Detects the method to call for fetching group members from the groups when grouping select options

Detects the label and value methods from a collection using methods set in collection_label_methods and collection_value_methods. For some ruby core classes sensible defaults have been defined. It will use and delete the options :label_method and :value_methods when present.

Outputs a label and a standard Rails email field inside the wrapper.

Outputs a label and a standard Rails file field inside the wrapper.

Used by check_boxes input. The selected values will be set by retrieving the value through the association.

If the collection is not a hash or an array of strings, fixnums or symbols, we use value_method to retrieve an array with the values

Outputs a hidden field inside the wrapper, which should be hidden with CSS. Additionals options can be given using :input_hml. Should :input_html not be specified every option except for formtastic options will be sent straight to hidden input element.

Generates an input for the given method using the type supplied with :as.

Generates the legend for radiobuttons and checkboxes

Outputs a label and standard Rails text field inside the wrapper.

Determines whether the given options evaluate to true

Outputs a label and standard Rails password field inside the wrapper.

Outputs a label and a standard Rails phone field inside the wrapper.

Outputs a fieldset containing a legend for the label text, and an ordered list (ol) of list items, one for each possible choice in the belongs_to association. Each li contains a label and a radio input.

Example:

  f.input :author, :as => :radio

Output:

  <fieldset>
    <legend><span>Author</span></legend>
    <ol>
      <li>
        <label for="book_author_id_1"><input id="book_author_id_1" name="book[author_id]" type="radio" value="1" /> Justin French</label>
      </li>
      <li>
        <label for="book_author_id_2"><input id="book_author_id_2" name="book[owner_id]" type="radio" value="2" /> Kate French</label>
      </li>
    </ol>
  </fieldset>

You can customize the choices available in the radio button set by passing in a collection (an Array or Hash) through the :collection option. If not provided, the choices are found by reflecting on the association (Author.all in the example above).

Examples:

  f.input :author, :as => :radio, :collection => @authors
  f.input :author, :as => :radio, :collection => Author.all
  f.input :author, :as => :radio, :collection => [@justin, @kate]
  f.input :author, :collection => ["Justin", "Kate", "Amelia", "Gus", "Meg"]

The :label_method option allows you to customize the label for each radio button two ways:

  • by naming the correct method to call on each object in the collection as a symbol (:name, :login, etc)
  • by passing a Proc that will be called on each object in the collection, allowing you to use helpers or multiple model attributes together

Examples:

  f.input :author, :as => :radio, :label_method => :full_name
  f.input :author, :as => :radio, :label_method => :login
  f.input :author, :as => :radio, :label_method => :full_name_with_post_count
  f.input :author, :as => :radio, :label_method => Proc.new { |a| "#{a.name} (#{pluralize("post", a.posts.count)})" }

The :value_method option provides the same customization of the value attribute of each option tag.

Examples:

  f.input :author, :as => :radio, :value_method => :full_name
  f.input :author, :as => :radio, :value_method => :login
  f.input :author, :as => :radio, :value_method => Proc.new { |a| "author_#{a.login}" }

Finally, you can set :value_as_class => true if you want the li wrapper around each radio button / label combination to contain a class with the value of the radio button (useful for applying specific CSS or Javascript to a particular radio button).

Outputs a label and a standard Rails search field inside the wrapper.

Outputs a label and a select box containing options from the parent (belongs_to, has_many, has_and_belongs_to_many) association. If an association is has_many or has_and_belongs_to_many the select box will be set as multi-select and size = 5

Example (belongs_to):

  f.input :author

  <label for="book_author_id">Author</label>
  <select id="book_author_id" name="book[author_id]">
    <option value=""></option>
    <option value="1">Justin French</option>
    <option value="2">Jane Doe</option>
  </select>

Example (has_many):

  f.input :chapters

  <label for="book_chapter_ids">Chapters</label>
  <select id="book_chapter_ids" name="book[chapter_ids]">
    <option value=""></option>
    <option value="1">Chapter 1</option>
    <option value="2">Chapter 2</option>
  </select>

Example (has_and_belongs_to_many):

  f.input :authors

  <label for="book_author_ids">Authors</label>
  <select id="book_author_ids" name="book[author_ids]">
    <option value=""></option>
    <option value="1">Justin French</option>
    <option value="2">Jane Doe</option>
  </select>

You can customize the options available in the select by passing in a collection. A collection can be given as an Array, a Hash or as a String (containing pre-rendered HTML options). If not provided, the choices are found by inferring the parent‘s class name from the method name and simply calling all on it (VehicleOwner.all in the example above).

Examples:

  f.input :author, :collection => @authors
  f.input :author, :collection => Author.all
  f.input :author, :collection => [@justin, @kate]
  f.input :author, :collection => {@justin.name => @justin.id, @kate.name => @kate.id}
  f.input :author, :collection => ["Justin", "Kate", "Amelia", "Gus", "Meg"]
  f.input :author, :collection => grouped_options_for_select(["North America",[["United States","US"],["Canada","CA"]]])

The :label_method option allows you to customize the text label inside each option tag two ways:

  • by naming the correct method to call on each object in the collection as a symbol (:name, :login, etc)
  • by passing a Proc that will be called on each object in the collection, allowing you to use helpers or multiple model attributes together

Examples:

  f.input :author, :label_method => :full_name
  f.input :author, :label_method => :login
  f.input :author, :label_method => :full_name_with_post_count
  f.input :author, :label_method => Proc.new { |a| "#{a.name} (#{pluralize("post", a.posts.count)})" }

The :value_method option provides the same customization of the value attribute of each option tag.

Examples:

  f.input :author, :value_method => :full_name
  f.input :author, :value_method => :login
  f.input :author, :value_method => Proc.new { |a| "author_#{a.login}" }

You can pass html_options to the select tag using :input_html => {}

Examples:

  f.input :authors, :input_html => {:size => 20, :multiple => true}

By default, all select inputs will have a blank option at the top of the list. You can add a prompt with the :prompt option, or disable the blank option with :include_blank => false.

You can group the options in optgroup elements by passing the :group_by option (Note: only tested for belongs_to relations)

Examples:

  f.input :author, :group_by => :continent

All the other options should work as expected. If you want to call a custom method on the group item. You can include the option:group_label_method Examples:

  f.input :author, :group_by => :continents, :group_label_method => :something_different

Outputs a label and standard Rails text field inside the wrapper.

Ouputs a label and standard Rails text area inside the wrapper.

Outputs a fieldset with a legend for the method label, and a ordered list (ol) of list items (li), one for each fragment for the time (hour, minute, second). Each li contains a label (eg "Hour") and a select box. Overwriting the label is possible by adding the :labels option. :labels should be a hash with the field (e.g. day) as key and the label text as value. See date_or_datetime_input for a more detailed output example.

Some of Rails’ options for select_time are supported, but not everything yet, see documentation of date_or_datetime_input() for more information.

Outputs a timezone select input as Rails’ time_zone_select helper. You can give priority zones as option.

Examples:

  f.input :time_zone, :as => :time_zone, :priority_zones => /Australia/

Outputs a label and a standard Rails url field inside the wrapper.

Returns the active validations for the given method or an empty Array if no validations are found for the method.

By default, the if/unless options of the validations are evaluated and only the validations that should be run for the current object state are returned. Pass :all to the last parameter to return :all validations regardless of if/unless options.

Requires the ValidationReflection plugin to be present or an ActiveModel. Returns an epmty Array if neither is the case.

[Validate]