Class: Formtastic::SemanticFormBuilder
- Inherits:
-
ActionView::Helpers::FormBuilder
- Object
- ActionView::Helpers::FormBuilder
- Formtastic::SemanticFormBuilder
- Defined in:
- lib/formtastic.rb
Direct Known Subclasses
Constant Summary collapse
- INPUT_MAPPINGS =
Keeps simple mappings in a hash
{ :string => :text_field, :password => :password_field, :numeric => :text_field, :text => :text_area, :file => :file_field }
- STRING_MAPPINGS =
[ :string, :password, :numeric ]
- @@default_text_field_size =
50
- @@all_fields_required_by_default =
true
- @@required_string =
proc { %{<abbr title="#{I18n.t 'formtastic.required', :default => 'required'}">*</abbr>} }
- @@optional_string =
''
- @@inline_errors =
:sentence
- @@label_str_method =
:humanize
- @@collection_label_methods =
%w[to_label display_name full_name name title username login value to_s]
- @@inline_order =
[ :input, :hints, :errors ]
- @@file_methods =
[ :file?, :public_filename ]
Instance Attribute Summary collapse
-
#nested_child_index ⇒ Object
writeonly
Sets the attribute nested_child_index.
-
#template ⇒ Object
Returns the value of attribute template.
Instance Method Summary collapse
-
#buttons(*args, &block) ⇒ Object
(also: #button_field_set)
Creates a fieldset and ol tag wrapping for form buttons / actions as list items.
-
#commit_button(value = nil, options = {}) ⇒ Object
Creates a submit input tag with the value “Save [model name]” (for existing records) or “Create [model name]” (for new records) by default:.
-
#input(method, options = {}) ⇒ Object
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. -
#inputs(*args, &block) ⇒ Object
(also: #input_field_set)
Creates an input fieldset and ol tag wrapping for use around a set of inputs.
-
#semantic_fields_for(record_or_name_or_array, *args, &block) ⇒ Object
A thin wrapper around #fields_for to set :builder => Formtastic::SemanticFormBuilder for nesting forms:.
Instance Attribute Details
#nested_child_index=(value) ⇒ Object (writeonly)
Sets the attribute nested_child_index
38 39 40 |
# File 'lib/formtastic.rb', line 38 def nested_child_index=(value) @nested_child_index = value end |
#template ⇒ Object
Returns the value of attribute template.
37 38 39 |
# File 'lib/formtastic.rb', line 37 def template @template end |
Instance Method Details
#buttons(*args, &block) ⇒ Object Also known as:
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.
265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/formtastic.rb', line 265 def (*args, &block) = args. [:class] ||= "buttons" if block_given? field_set_and_list_wrapping(, &block) else args = [:commit] if args.empty? contents = args.map { || send(:"#{button_name}_button") } field_set_and_list_wrapping(, contents) end end |
#commit_button(value = nil, options = {}) ⇒ Object
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" />
288 289 290 291 |
# File 'lib/formtastic.rb', line 288 def (value=nil, = {}) value ||= template.content_tag(:li, template.submit_tag(value), :class => "commit") end |
#input(method, options = {}) ⇒ Object
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 (or fieldset legend) text
-
: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
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
-
:radio (a set of radio inputs for associations) - default to association names
-
: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
Example:
<% semantic_form_for @employee do |form| %>
<% form.inputs do -%>
<%= form.input :name, :label => "Full Name"%>
<%= form.input :manager_id, :as => :radio %>
<%= form.input :hired_at, :as => :date, :label => "Date Hired" %>
<%= form.input :phone, :required => false, :hint => "Eg: +1 555 1234" %>
<% end %>
<% end %>
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/formtastic.rb', line 79 def input(method, = {}) [:required] = method_required?(method, [:required]) [:as] ||= default_input_type(method) [:label] ||= if @object @object.class.human_attribute_name(method.to_s) else method.to_s.send(@@label_str_method) end if [:boolean_select, :boolean_radio].include?([:as]) ::ActiveSupport::Deprecation.warn(":as => :#{options[:as]} is deprecated, use :as => :#{options[:as].to_s[8..-1]} instead", caller[3..-1]) end html_class = [ [:as], ([:required] ? :required : :optional) ].join(' ') html_class << ' error' if @object && @object.errors.on(method.to_s) html_id = generate_html_id(method) list_item_content = @@inline_order.map do |type| send(:"inline_#{type}_for", method, ) end.compact.join("\n") return template.content_tag(:li, list_item_content, { :id => html_id, :class => html_class }) end |
#inputs(*args, &block) ⇒ Object Also known as: input_field_set
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 %>
Options
All options (with the exception of :name) are passed down to the fieldset as HTML attributes (id, class, style, etc). If provided, the :name option is passed into a legend tag inside the fieldset (otherwise a legend is not generated).
# 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 %>
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 %>
<% 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>
</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.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.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).
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/formtastic.rb', line 232 def inputs(*args, &block) = args. [:class] ||= "inputs" if fields_for_object = .delete(:for) .merge!(:parent_builder => self) inputs_for_nested_attributes(fields_for_object, args << , .delete(:for_options) || {}, &block) elsif block_given? field_set_and_list_wrapping(, &block) else if @object && args.empty? # Get all belongs_to association args = @object.class.reflections.map { |n,_| n if _.macro == :belongs_to } # Get content columns and remove timestamps columns from it args += @object.class.content_columns.map(&:name) args -= %w[created_at updated_at created_on updated_on] args.compact! end contents = args.map { |method| input(method.to_sym) } field_set_and_list_wrapping(, contents) end end |
#semantic_fields_for(record_or_name_or_array, *args, &block) ⇒ Object
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>
312 313 314 315 316 317 |
# File 'lib/formtastic.rb', line 312 def semantic_fields_for(record_or_name_or_array, *args, &block) opts = args. opts.merge!(:builder => Formtastic::SemanticFormBuilder) args.push(opts) fields_for(record_or_name_or_array, *args, &block) end |