Module: Formtastic::Helpers::ButtonsHelper

Includes:
FieldsetWrapper, LocalizedString
Included in:
FormBuilder
Defined in:
lib/formtastic/helpers/buttons_helper.rb

Overview

ButtonsHelper encapsulates the responsibilties of the #buttons and #commit_button helpers for submitting forms.

#buttons is used to wrap the form’s button(s) and actions in a ‘<fieldset>` and `<ol>`, with each item in the list containing the markup representing a single button.

#buttons is usually called with a block containing a single #commit_button call:

<%= semantic_form_for @post do |f| %>
  ...
  <%= f.buttons do %>
    <%= f.commit_button
  <% end %>
<% end %>

The HTML output will be something like:

<form class="formtastic" method="post" action="...">
  ...
  <fieldset class="buttons">
    <ol>
      <li class="commit">
        <input type="submit" name="commit" value="Create Post" class="create">
      </li>
    </ol>
  </fieldset>
</form>

While this may seem slightly over-engineered, it is consistent with the way form inputs are handled, and makes room for other types of buttons and actions in future versions (such as cancel buttons or links, reset buttons and even alternate actions like ‘save and continue editing’).

It’s important to note that the ‘semantic_form_for` and #buttons blocks wrap the standard Rails `form_for` helper and form builder, so you have full access to every standard Rails form helper, with any HTML markup and ERB syntax, allowing you to “break free” from Formtastic when it doesn’t suit to create your own buttons, links and actions:

<%= semantic_form_for @post do |f| %>
  ...
  <%= f.buttons do %>
    <li class="save">
      <%= f.submit "Save" %>
    <li>
    <li class="cancel-link">
      Or <%= link_to "Cancel", posts_url %>
    <li>
  <% end %>
<% end %>

There are many other syntax variations and arguments to customize your form. See the full documentation of #buttons and #commit_button for details.

Instance Method Summary collapse

Instance Method Details

#buttons(*args, &block) ⇒ Object

TODO:

document i18n keys

Creates a fieldset and ol tag wrapping for use around a set of buttons. 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 named buttons. These two examples are functionally equivalent:

# With a block:
<% semantic_form_for @post do |f| %>
  ...
  <% f.buttons do %>
    <%= f.commit_button %>
  <% end %>
<% end %>

# With a list of fields:
<% semantic_form_for @post do |f| %>
  <%= f.buttons :commit %>
<% end %>

# Output:
<form ...>
  <fieldset class="inputs">
    <ol>
      <li class="commit">
        <input type="submit" ...>
      </li>
    </ol>
  </fieldset>
</form>

Only one type of named button is supported at this time (:commit), and it’s assumed to be the default choice, so this is also functionally equivalent, but may change in the future:

# With no args:
<% semantic_form_for @post do |f| %>
  ...
  <%= f.buttons %>
<% end %>

While this may seem slightly over-engineered, it is consistent with the way form inputs are handled, and makes room for other types of buttons and actions in future versions (such as cancel buttons or links, reset buttons and even alternate actions like ‘save and continue editing’).

All options except ‘:name` and `:title` are passed down to the fieldset as HTML attributes (`id`, `class`, `style`…). If provided, the `:name` or `:title` option is passed into a `<legend>` inside the `<fieldset>` to name the set of buttons.

Examples:

Quickly add button(s) to the form, accepting all default values, options and behaviors

<% semantic_form_for @post do |f| %>
  ...
  <%= f.buttons %>
<% end %>

Specify which named buttons you want, accepting all default values, options and behaviors

<% semantic_form_for @post do |f| %>
  ...
  <%= f.buttons :commit %>
<% end %>

Specify which named buttons you want, and name the fieldset

<% semantic_form_for @post do |f| %>
  ...
  <%= f.buttons :commit, :name => "Actions" %>
  or
  <%= f.buttons :commit, :label => "Actions" %>
<% end %>

Get full control over the commit_button options

<% semantic_form_for @post do |f| %>
  ...
  <%= f.buttons do %>
    <%= f.commit_button :label => "Go", :input_html => { ... }, :wrapper_html => { ... }
  <% end %>
<% end %>

Make your own custom buttons, links or actions with standard Rails helpers or HTML

<% semantic_form_for @post do |f| %>
  ...
  <%= f.buttons do %>
    <li class="submit">
      <%= f.submit "Submit" %>
    </li>
    <li class="reset">
      <input type="reset" value="Reset">
    </li>
    <li class="cancel">
      <%= link_to "Cancel", posts_url %>
    </li>
  <% end %>
<% end %>

Add HTML attributes to the fieldset

<% semantic_form_for @post do |f| %>
  ...
  <%= f.buttons :commit, :style => "border:1px;" %>
  or
  <%= f.buttons :style => "border:1px;" do %>
    ...
  <% end %>
<% end %>

Parameters:

  • *args (Hash)

    a customizable set of options



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/formtastic/helpers/buttons_helper.rb', line 167

def buttons(*args, &block)
  html_options = args.extract_options!
  html_options[:class] ||= "buttons"

  if block_given?
    field_set_and_list_wrapping(html_options, &block)
  else
    args = [:commit] if args.empty?
    contents = args.map { |button_name| send(:"#{button_name}_button") }
    field_set_and_list_wrapping(html_options, contents)
  end
end

#commit_button(*args) ⇒ Object

TODO:

document i18n keys

TODO:

strange that ‘:accesskey` seems to be supported in the top level args as well as `:button_html`

Creates a submit input tag with the value “Save [model name]” (for existing records) or “Create [model name]” (for new records) by default. The output is an ‘<input>` tag with the `type` of `submit` and a class of either `create` or `update` (if Formtastic can determin if) the record is new or not) with `submit` as a fallback class. The submit button is wrapped in an `<li>` tag with a class of `commit`, and is intended to be rendered inside a #buttons block which wraps the button in a `fieldset` and `ol`.

The textual value of the label can be changed from this default through the ‘:label` argument or through i18n.

You can pass HTML attributes down to the ‘<input>` tag with the `:button_html` option, and pass HTML attributes to the wrapping `<li>` tag with the `:wrapper_html` option.

Examples:

Basic usage

# form
<%= semantic_form_for @post do |f| %>
  ...
  <%= f.buttons do %>
    <%= f.commit_button %>
  <% end %>
<% end %>

# output
<form ...>
  ...
  <fieldset class="buttons">
    <input name="commit" type="submit" value="Create Post" class="create">
  </fieldset>
</form>

Set the value through the ‘:label` option

<%= f.commit_button :label => "Go" %>

Set the value through the optional first argument (like Rails’ ‘f.submit`)

<%= f.commit_button "Go" %>

Pass HTML attributes down to the ‘<input>`

<%= f.commit_button :button_html => { :class => 'pretty', :accesskey => 'g' } %>
<%= f.commit_button :label => "Go", :button_html => { :class => 'pretty', :accesskey => 'g' } %>
<%= f.commit_button "Go", :button_html => { :class => 'pretty', :accesskey => 'g' } %>

Pass HTML attributes down to the ‘<li>` wrapper

<%= f.commit_button :button_html => { :class => 'special', :id => 'whatever' } %>
<%= f.commit_button :label => "Go", :button_html => { :class => 'special', :id => 'whatever' } %>
<%= f.commit_button "Go", :button_html => { :class => 'special', :id => 'whatever' } %>

Parameters:

  • *args (Hash)

    a customizable set of options



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/formtastic/helpers/buttons_helper.rb', line 237

def commit_button(*args)
  options = args.extract_options!
  text = options.delete(:label) || args.shift

  if @object && (@object.respond_to?(:persisted?) || @object.respond_to?(:new_record?))
    key = @object.persisted? ? :update : :create

    # Deal with some complications with ActiveRecord::Base.human_name and two name models (eg UserPost)
    # ActiveRecord::Base.human_name falls back to ActiveRecord::Base.name.humanize ("Userpost")
    # if there's no i18n, which is pretty crappy.  In this circumstance we want to detect this
    # fall back (human_name == name.humanize) and do our own thing name.underscore.humanize ("User Post")
    if @object.class.model_name.respond_to?(:human)
      object_name = @object.class.model_name.human
    else
      object_human_name = @object.class.human_name                # default is UserPost => "Userpost", but i18n may do better ("User post")
      crappy_human_name = @object.class.name.humanize             # UserPost => "Userpost"
      decent_human_name = @object.class.name.underscore.humanize  # UserPost => "User post"
      object_name = (object_human_name == crappy_human_name) ? decent_human_name : object_human_name
    end
  else
    key = :submit
    object_name = @object_name.to_s.send(label_str_method)
  end

  text = (localized_string(key, text, :action, :model => object_name) ||
          Formtastic::I18n.t(key, :model => object_name)) unless text.is_a?(::String)

  button_html = options.delete(:button_html) || {}
  button_html.merge!(:class => [button_html[:class], key].compact.join(' '))

  wrapper_html_class = ['commit'] # TODO: Add class reflecting on form action.
  wrapper_html = options.delete(:wrapper_html) || {}
  wrapper_html[:class] = (wrapper_html_class << wrapper_html[:class]).flatten.compact.join(' ')

  accesskey = (options.delete(:accesskey) || default_commit_button_accesskey) unless button_html.has_key?(:accesskey)
  button_html = button_html.merge(:accesskey => accesskey) if accesskey
  template.(:li, Formtastic::Util.html_safe(submit(text, button_html)), wrapper_html)
end