h2. SimpleForm 2.0和 Formtastic 的整体比较
Formtastic 的主要缺点在于对HTML输出的可定制性上不够灵活。目前的系统中,想要满足各种表单的需求,就需要在每个表单页写很多重复的代码进行设置,甚至很多页面都在使用 Rails 原生的 Form Builder,这样做维护量太大。
SimpleForm 在用法上与 Formtastic 类似,同样很好的支持了I18n、表间关联、嵌套表单和表单验证等常用的功能。SimpleForm 从 2.0 开始,在可定制性上有质的突破(Twitter Bootstrap 在里边起了很关键的作用),现在的它更像是一个 Form Builder 框架,可以很方便的对它进行设置和扩展。
h2. 使用 SimpleForm 替换 Formtastic 需要做的修改
# 把 @semantic_form_for@ 替换为 @simple_form_for@
# 去掉 @<%= f.inputs do %> ... <% end %>@ 和 @<%= f.buttons do %> ... <% end %>@,替换成对应的div
h2. SimpleForm 2.0使用方法
h3. 1、核心概念:wrapper
*通常一个表单项有这些部分(SimpleForm文档中称为 component):*
# label
# input
# hint
# error
# 把上面4个 component 包含在内部的一个“容器”,通常会是一个div标签
把以上的“容器”及其内部的各个元素看成一个整体,就是一个 wrapper 了。如果把 textarea、select 这些看成是和 input 等价的东西,那么一个表单就是N个顺序排列的 wrapper 组成的。在 SimpleForm 中,对表单进行定制时,只需在配置文件中设置好N种 wrapper,然后在 _form.html.erb 中进行正常调用即可。默认情况下,一个表单中的各个表单项都使用相同的 wrapper,我们还可以对每一个表单项单独设置,以满足特殊的定制需求。在更极端的情况下,当然也可以在表单页面直接设置 HTML 标签、class 等。有了 wrapper,不管是先出前端页面,还是后端表单模板写好后需要更改,只要同样类型表单的 HTML 和 CSS 结构相对统一,就能大量的减少我们的工作量。
h3. 2、使用示例
<%= simple_form_for @staffer, validate: true do |f| %>
<%= f.input :username, wrapper: :inline %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
<%= f.input :email %>
<%= f.input :fullname %>
<%= f.button :submit %>
<% end %>
h3. 3、配置 SimpleForm
配置文件位于config/initializers/simple_form.rb,以 Bootstrap 的默认配置进行说明:
SimpleForm.setup do |config|
# 定义一个名字为 :default 的 wrapper
config.wrappers :default, :class => :input,
:hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
# 输出 HTML5 标签
b.use :html5
# Calculates placeholders automatically from I18n
# You can also pass a string as f.input :placeholder => "Placeholder"
b.use :placeholder
## Optional extensions
# They are disabled unless you pass `f.input EXTENSION_NAME => :lookup`
# to the input. If so, they will retrieve the values from the model
# if any exists. If you want to enable the lookup for any of those
# extensions by default, you can change `b.optional` to `b.use`.
# Calculates maxlength from length validations for string inputs
b.optional :maxlength
# Calculates pattern from format validations for string inputs
b.optional :pattern
# Calculates min and max from length validations for numeric inputs
b.optional :min_max
# Calculates readonly automatically from readonly attributes
b.optional :readonly
# :label_input 是 :label 和 :input 的打包,后边会看到它们单独出现的情况
# label、input、hint 和 error 在表单中的顺序由他们在配置文件中定义的顺序决定
b.use :label_input
b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
b.use :error, :wrap_with => { :tag => :span, :class => :error }
end
# 通过参数定制最外层的“容器”的标签为 div.control-group
config.wrappers :bootstrap, :tag => 'div', :class => 'control-group', :error_class => 'error' do |b|
b.use :html5
b.use :placeholder
b.use :label
# 这个 wrapper 方法可以嵌套,调用它可以在输出结果中增加一个 HTML 标签
b.wrapper :tag => 'div', :class => 'controls' do |ba|
ba.use :input
# 定制出错信息包含在一个 span.help-inline 标签中
ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
# 定制提示信息包含在一个 p.help-block 标签中
ba.use :hint, :wrap_with => { :tag => 'p', :class => 'help-block' }
end
end
config.wrappers :prepend, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
b.use :html5
b.use :placeholder
b.use :label
b.wrapper :tag => 'div', :class => 'controls' do |input|
# 这里就使用了嵌套的 wrapper 以输出 2 层 div 标签
input.wrapper :tag => 'div', :class => 'input-prepend' do |prepend|
prepend.use :input
end
input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
end
end
config.wrappers :append, :tag => 'div', :class => "control-group", :error_class => 'error' do |b|
b.use :html5
b.use :placeholder
b.use :label
b.wrapper :tag => 'div', :class => 'controls' do |input|
input.wrapper :tag => 'div', :class => 'input-append' do |append|
append.use :input
end
input.use :hint, :wrap_with => { :tag => 'span', :class => 'help-block' }
input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' }
end
end
# 设置默认 wrapper
config.default_wrapper = :bootstrap
# 单选按钮和复选框与 label 的位置关系,:nested 是专门为 Bootstrap定制的,我们通常用 :inline
# :inline => input + label
# :nested => label > input
config.boolean_style = :nested
# 按钮默认的 class
config.button_class = 'btn'
# Default tag used for error notification helper.
config.error_notification_tag = :div
# CSS class to add for error notification helper.
config.error_notification_class = 'alert alert-error'
# 设置必填项的 label 中星号放到文字后边
config.label_text = lambda { |label, required| "#{label} #{required}" }
# 设置 label 的 class,默认为 nil
config.label_class = 'control-label'
# 表单的默认 class
config.form_class = :simple_form
# 禁止浏览器对表单校验(HTML5),因为客户端校验我们都使用JavaScript插件,以便各浏览器效果统一
config.browser_validations = false
# 表单输入框默认长度
config.default_input_size = 20
end
*因为注释中的代码看不清,我删除了很多默认设置选项,更多参数说明及用法请看:* https://github.com/plataformatec/simple_form https://github.com/plataformatec/simple_form/wiki