Action View 表单助手
与使用普通 HTML 相比,表单助手旨在使处理资源变得更加容易。
通常,用于创建或更新资源的表单通过多种方式反映资源的标识:(i) 表单发送到的 URL(表单元素的 action
属性)应导致请求被路由到适当的控制器操作(在现有资源的情况下,具有适当的 :id
参数),(ii) 输入字段应以这样的方式命名,以便在控制器中它们的值出现在 params
哈希中的适当位置,以及 (iii) 对于现有记录,当表单最初显示时,与资源属性相对应的输入字段应显示这些属性的当前值。
在 Rails 中,这通常是通过使用 form_with
或 form_for
和许多相关助手方法来创建表单来实现的。这些方法生成一个适当的 form
标签,并生成一个表单构建器对象,该对象知道表单所针对的模型。输入字段是通过调用在表单构建器上定义的方法创建的,这意味着它们能够生成与模型属性相对应的适当名称和默认值,以及方便的 ID 等。生成的字段名称中的约定允许控制器接收表单数据在 params
中以良好的结构化方式,而无需您费心。
例如,要创建一个新的人,您通常在 PeopleController#new
操作中设置 Person
的一个新实例 @person
,并在视图模板中将该对象传递给 form_with
或 form_for
<%= form_with model: @person do |f| %>
<%= f.label :first_name %>:
<%= f.text_field :first_name %><br />
<%= f.label :last_name %>:
<%= f.text_field :last_name %><br />
<%= f.submit %>
<% end %>
为此生成的 HTML 将是(模数格式化)
<form action="/people" class="new_person" id="new_person" method="post">
<input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
<label for="person_first_name">First name</label>:
<input id="person_first_name" name="person[first_name]" type="text" /><br />
<label for="person_last_name">Last name</label>:
<input id="person_last_name" name="person[last_name]" type="text" /><br />
<input name="commit" type="submit" value="Create Person" />
</form>
如您所见,HTML 反映了资源的知识,例如表单应提交到的路径或输入字段的名称。
特别是,由于生成的字段名称遵循的约定,控制器得到了一个嵌套的哈希 params[:person]
,其中包含在表单中设置的人员属性。该哈希已准备好传递给 Person.new
@person = Person.new(params[:person])
if @person.save
# success
else
# error handling
end
有趣的是,前面的示例中的完全相同的视图代码可用于编辑一个人。如果 @person
是一个现有的记录,其名称为“John Smith”,ID 为 256,则上面的代码按原样将改为生成
<form action="/people/256" class="edit_person" id="edit_person_256" method="post">
<input name="_method" type="hidden" value="patch" />
<input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
<label for="person_first_name">First name</label>:
<input id="person_first_name" name="person[first_name]" type="text" value="John" /><br />
<label for="person_last_name">Last name</label>:
<input id="person_last_name" name="person[last_name]" type="text" value="Smith" /><br />
<input name="commit" type="submit" value="Update Person" />
</form>
请注意,端点、默认值和提交按钮标签是针对 @person
定制的。之所以能这样工作,是因为涉及的助手知道资源是新记录还是现有记录,并相应地生成 HTML。
控制器将再次在 params[:person]
中接收表单数据,已准备好传递给 Person#update
if @person.update(params[:person])
# success
else
# error handling
end
这就是您通常处理资源的方式。
- C
- D
- E
- F
- H
- L
- M
- N
- P
- R
- S
- T
- U
- W
实例公共方法
check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") 链接
checkbox(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") 链接
返回一个复选框标签,该标签专用于访问分配给模板的对象(由 object
标识)上的指定属性(由 method
标识)。该对象必须是实例对象 (@object) 而不是局部对象。它的目的是 method
返回一个整数,如果该整数大于零,则选中复选框。可以在 options
中以哈希形式传递输入标签上的其他选项。checked_value
默认值为 1,而默认的 unchecked_value
设置为 0,这对于布尔值很方便。
选项
-
可以传递任何标准 HTML 属性以供标签使用,例如
:class
。 -
:checked
-true
或false
强制复选框的状态选中或不选中。 -
:include_hidden
- 如果设置为 false,则不会生成下面描述的辅助隐藏字段。
陷阱
HTML 规范指出未选中的复选框不成功,因此 Web 浏览器不会发送它们。不幸的是,这会带来一个陷阱:如果一个 Invoice
模型有一个 paid
标志,并且在编辑已付款发票的表单中,用户取消选中其复选框,则不会发送任何 paid
参数。因此,任何类似于以下的批量赋值成语都不会更新标志。
@invoice.update(params[:invoice])
不会更新标志。
为了防止这种情况,助手会在每个复选框之前生成一个辅助隐藏字段。隐藏字段具有相同的名称,其属性模拟未选中的复选框。
这样一来,客户端要么只发送隐藏字段(表示未选中复选框),要么发送两个字段。由于 HTML 规范指出键值对必须以其在表单中出现的顺序发送,并且参数提取获取查询字符串中任何重复键的最后一个出现位置,因此这对普通表单有效。
不幸的是,当复选框位于类似数组的参数中时,该解决方法不起作用,例如
<%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>
<%= form.checkbox :paid %>
...
<% end %>
因为参数名称重复正是 Rails 用于区分数组元素的内容。对于每个带有选中复选框的项目,您都会得到一个额外的幽灵项目,其中只有该属性被分配为“0”。
在这种情况下,最好使用 checkbox_tag
或使用哈希而不是数组。
示例
# Let's say that @article.validated? is 1:
checkbox("article", "validated")
# => <input name="article[validated]" type="hidden" value="0" />
# <input checked="checked" type="checkbox" id="article_validated" name="article[validated]" value="1" />
# Let's say that @puppy.gooddog is "no":
checkbox("puppy", "gooddog", {}, "yes", "no")
# => <input name="puppy[gooddog]" type="hidden" value="no" />
# <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
checkbox("eula", "accepted", { class: 'eula_check' }, "yes", "no")
# => <input name="eula[accepted]" type="hidden" value="no" />
# <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1347 def checkbox(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") Tags::CheckBox.new(object_name, method, self, checked_value, unchecked_value, options).render end
color_field(object_name, method, options = {}) 链接
返回一个类型为“color”的 text_field
。
color_field("car", "color")
# => <input id="car_color" name="car[color]" type="color" value="#000000" />
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1378 def color_field(object_name, method, options = {}) Tags::ColorField.new(object_name, method, self, options).render end
date_field(object_name, method, options = {}) 链接
返回一个类型为“date”的 text_field
。
date_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="date" />
默认值是通过尝试对对象的 value 调用 strftime
(使用“%Y-%m-%d”)生成的,这使其对 DateTime
和 ActiveSupport::TimeWithZone
的实例表现得如预期一样。您仍然可以通过显式传递“value”选项来覆盖它,例如
@user.born_on = Date.new(1984, 1, 27)
date_field("user", "born_on", value: "1984-05-12")
# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-05-12" />
您可以通过将 Date
或 Time
的实例传递给选项哈希来创建“min”和“max”属性的值。
date_field("user", "born_on", min: Date.today)
# => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" />
或者,您可以将格式为 ISO8601 日期字符串的 String
传递为“min”和“max”的值。
date_field("user", "born_on", min: "2014-05-20")
# => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" />
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1442 def date_field(object_name, method, options = {}) Tags::DateField.new(object_name, method, self, options).render end
datetime_field(object_name, method, options = {}) 链接
返回一个类型为“datetime-local”的 text_field
。
datetime_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" />
默认值是通过尝试对对象的 value 调用 strftime
(使用“%Y-%m-%dT%T”)生成的,这使其对 DateTime
和 ActiveSupport::TimeWithZone
的实例表现得如预期一样。
@user.born_on = Date.new(1984, 1, 12)
datetime_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="1984-01-12T00:00:00" />
您可以通过将 Date
或 Time
的实例传递给选项哈希来创建“min”和“max”属性的值。
datetime_field("user", "born_on", min: Date.today)
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />
或者,您可以将格式为 ISO8601 日期时间字符串的 String
传递为“min”和“max”的值。
datetime_field("user", "born_on", min: "2014-05-20T00:00:00")
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />
默认情况下,提供的日期时间将以包含秒的形式进行格式化。您可以通过传递 include_seconds: false
来仅呈现日期、小时和分钟。
@user.born_on = Time.current
datetime_field("user", "born_on", include_seconds: false)
# => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="2014-05-20T14:35" />
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1515 def datetime_field(object_name, method, options = {}) Tags::DatetimeLocalField.new(object_name, method, self, options).render end
email_field(object_name, method, options = {}) 链接
返回一个类型为“email”的 text_field
。
email_field("user", "address")
# => <input id="user_address" name="user[address]" type="email" />
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1569 def email_field(object_name, method, options = {}) Tags::EmailField.new(object_name, method, self, options).render end
fields(scope = nil, model: nil, **options, &block) 链接
使用显式范围或模型对输入字段进行作用域。与 form_with
使用 :scope
或 :model
的方式相同,只是它不输出表单标签。
# Using a scope prefixes the input field names:
<%= fields :comment do |fields| %>
<%= fields.text_field :body %>
<% end %>
# => <input type="text" name="comment[body]">
# Using a model infers the scope and assigns field values:
<%= fields model: Comment.new(body: "full bodied") do |fields| %>
<%= fields.text_field :body %>
<% end %>
# => <input type="text" name="comment[body]" value="full bodied">
# Using +fields+ with +form_with+:
<%= form_with model: @article do |form| %>
<%= form.text_field :title %>
<%= form.fields :comment do |fields| %>
<%= fields.text_field :body %>
<% end %>
<% end %>
与 form_with
非常相似,它生成一个与范围或模型关联的 FormBuilder
实例,因此任何生成的字段名称都将以传递的范围或从 :model
推断出的范围为前缀。
与其他表单助手混合使用
虽然 form_with
使用 FormBuilder
对象,但您可以混合使用独立的 FormHelper
方法和 FormTagHelper 中的方法
<%= fields model: @comment do |fields| %>
<%= fields.text_field :body %>
<%= textarea :commenter, :biography %>
<%= checkbox_tag "comment[all_caps]", "1", @comment.commenter.hulk_mode? %>
<% end %>
对于旨在使用对象作为基础的 FormOptionsHelper
和 DateHelper
中的方法也是如此,例如 FormOptionsHelper#collection_select
和 DateHelper#datetime_select
。
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1080 def fields(scope = nil, model: nil, **options, &block) options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options) if model model = _object_for_form_builder(model) scope ||= model_name_from_record_or_class(model).param_key end builder = instantiate_builder(scope, model, options) capture(builder, &block) end
fields_for(record_name, record_object = nil, options = {}, &block) 链接
在特定模型对象周围创建作用域,类似于 form_with
,但不会创建表单标签本身。这使得 fields_for
适用于在同一表单中指定其他模型对象。
虽然 fields_for
的用法和目的与 form_with
类似,但其方法签名略有不同。与 form_with
一样,它会将与特定模型对象关联的 FormBuilder
对象传递给一个代码块,并在代码块内允许在生成器上调用方法以生成与模型对象关联的字段。字段可以通过两种方式反映模型对象 - 它们是如何命名的(因此提交的值如何在控制器中的 params
哈希中出现)以及表单字段首次显示时显示的默认值。为了独立指定这两种功能,可以分别将对象名称(由符号或字符串表示)和对象本身传递给方法 -
<%= form_with model: @person do |person_form| %>
First name: <%= person_form.text_field :first_name %>
Last name : <%= person_form.text_field :last_name %>
<%= fields_for :permission, @person.permission do |permission_fields| %>
Admin? : <%= permission_fields.checkbox :admin %>
<% end %>
<%= person_form.submit %>
<% end %>
在这种情况下,复选框字段将由一个 HTML input
标签表示,该标签的 name
属性为 permission[admin]
,提交的值将出现在控制器中,为 params[:permission][:admin]
。如果 @person.permission
是一个现有记录,其属性为 admin
,则首次显示时复选框的初始状态将反映 @person.permission.admin
的值。
通常可以通过仅将模型对象的名称传递给 fields_for
来简化此操作 -
<%= fields_for :permission do |permission_fields| %>
Admin?: <%= permission_fields.checkbox :admin %>
<% end %>
…在这种情况下,如果 :permission
也恰好是实例变量 @permission
的名称,则输入字段的初始状态将反映该变量属性 @permission.admin
的值。
或者,您也可以只传递模型对象本身(如果第一个参数不是字符串或符号,fields_for
将意识到名称已被省略) -
<%= fields_for @person.permission do |permission_fields| %>
Admin?: <%= permission_fields.checkbox :admin %>
<% end %>
并且 fields_for
将从模型对象的类推导出所需的字段名称,例如,如果 @person.permission
的类为 Permission
,则字段仍然名为 permission[admin]
。
注意:这也适用于 FormOptionsHelper
和 DateHelper
中的方法,这些方法旨在将对象用作基础,例如 FormOptionsHelper#collection_select
和 DateHelper#datetime_select
。
嵌套属性示例
当属于当前作用域的对象对某个属性具有嵌套属性写入器时,fields_for
将为该属性生成一个新的作用域。这使您可以创建表单,这些表单可以一次性设置或更改父对象及其关联的属性。
嵌套属性写入器是正常设置器方法,以关联命名。定义这些写入器最常见的方法是在模型定义中使用 accepts_nested_attributes_for
或者定义具有适当名称的方法。例如:关联 :address
的属性写入器称为 address_attributes=
。
将生成一对一还是一对多样式的表单生成器取决于正常的读取器方法是返回单个对象还是数组对象。
一对一
考虑一个 Person 类,它从 address
读取器方法返回单个地址,并响应 address_attributes=
写入器方法
class Person
def address
@address
end
def address_attributes=(attributes)
# Process the attributes hash
end
end
现在,可以使用嵌套的 fields_for
使用此模型,如下所示
<%= form_with model: @person do |person_form| %>
...
<%= person_form.fields_for :address do |address_fields| %>
Street : <%= address_fields.text_field :street %>
Zip code: <%= address_fields.text_field :zip_code %>
<% end %>
...
<% end %>
当地址已经是 Person 上的关联时,您可以使用 accepts_nested_attributes_for
为您定义写入器方法
class Person < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address
end
如果您希望通过表单销毁关联的模型,则必须首先使用 :allow_destroy
选项为 accepts_nested_attributes_for
启用它
class Person < ActiveRecord::Base
has_one :address
accepts_nested_attributes_for :address, allow_destroy: true
end
现在,当您使用具有 _destroy
参数的表单元素时,其值为 true
,您将销毁关联的模型(例如 1、‘1’、true 或 ‘true’)。
<%= form_with model: @person do |person_form| %>
...
<%= person_form.fields_for :address do |address_fields| %>
...
Delete: <%= address_fields.checkbox :_destroy %>
<% end %>
...
<% end %>
一对多
考虑一个 Person 类,它从 projects
读取器方法返回一个数组 Project 实例,并响应 projects_attributes=
写入器方法
class Person
def projects
[@project1, @project2]
end
def projects_attributes=(attributes)
# Process the attributes hash
end
end
请注意,projects_attributes=
写入器方法实际上是 fields_for
正确识别 :projects
作为集合所必需的,并且表单标记中将设置正确的索引。
当项目已经是 Person 上的关联时,您可以使用 accepts_nested_attributes_for
为您定义写入器方法
class Person < ActiveRecord::Base
has_many :projects
accepts_nested_attributes_for :projects
end
现在,可以使用嵌套的 fields_for
使用此模型。传递给嵌套的 fields_for
调用的代码块将为集合中的每个实例重复
<%= form_with model: @person do |person_form| %>
...
<%= person_form.fields_for :projects do |project_fields| %>
<% if project_fields.object.active? %>
Name: <%= project_fields.text_field :name %>
<% end %>
<% end %>
...
<% end %>
还可以指定要使用的实例
<%= form_with model: @person do |person_form| %>
...
<% @person.projects.each do |project| %>
<% if project.active? %>
<%= person_form.fields_for :projects, project do |project_fields| %>
Name: <%= project_fields.text_field :name %>
<% end %>
<% end %>
<% end %>
...
<% end %>
或要使用的集合
<%= form_with model: @person do |person_form| %>
...
<%= person_form.fields_for :projects, @active_projects do |project_fields| %>
Name: <%= project_fields.text_field :name %>
<% end %>
...
<% end %>
如果您希望通过表单销毁任何关联的模型,则必须首先使用 :allow_destroy
选项为 accepts_nested_attributes_for
启用它
class Person < ActiveRecord::Base
has_many :projects
accepts_nested_attributes_for :projects, allow_destroy: true
end
这将允许您通过添加一个用于 _destroy
参数的表单元素来指定要销毁的模型,其值为 true
(例如 1、‘1’、true 或 ‘true’)。
<%= form_with model: @person do |person_form| %>
...
<%= person_form.fields_for :projects do |project_fields| %>
Delete: <%= project_fields.checkbox :_destroy %>
<% end %>
...
<% end %>
当使用集合时,您可能想知道数组中每个对象的索引。为此,index
方法在 FormBuilder
对象中可用。
<%= form_with model: @person do |person_form| %>
...
<%= person_form.fields_for :projects do |project_fields| %>
Project #<%= project_fields.index %>
...
<% end %>
...
<% end %>
请注意,fields_for
将自动生成一个隐藏字段以存储记录的 ID(如果它响应 persisted?
)。在某些情况下,不需要此隐藏字段,您可以传递 include_id: false
以阻止 fields_for
自动渲染它。
来源:显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1029 def fields_for(record_name, record_object = nil, options = {}, &block) options = { model: record_object, allow_method_names_outside_object: false, skip_default_ids: false }.merge!(options) fields(record_name, **options, &block) end
file_field(object_name, method, options = {}) 链接
返回一个文件上传输入标签,专门用于访问分配给模板的对象(由 object
标识)上的指定属性(由 method
标识)。输入标签上的其他选项可以作为哈希传递给 options
。这些选项将作为 HTML 元素属性标记到 HTML 中,如所示示例。
在 form_with
块中使用此方法将将封闭表单的编码设置为 multipart/form-data
。
选项
-
为标签创建标准 HTML 属性。
-
:disabled
- 如果设置为 true,则用户将无法使用此输入。 -
:multiple
- 如果设置为 true,*在大多数更新的浏览器中*,用户将被允许选择多个文件。 -
:include_hidden
- 当multiple: true
且include_hidden: true
时,该字段将以<input type="hidden">
字段为前缀,该字段的值为空,以支持提交空的文件集合。 -
:accept
- 如果设置为一个或多个 MIME 类型,则在选择文件时将向用户建议一个过滤器。您仍然需要设置模型验证。
示例
file_field(:user, :avatar)
# => <input type="file" id="user_avatar" name="user[avatar]" />
file_field(:article, :image, multiple: true)
# => <input type="file" id="article_image" name="article[image][]" multiple="multiple" />
file_field(:article, :attached, accept: 'text/html')
# => <input accept="text/html" type="file" id="article_attached" name="article[attached]" />
file_field(:article, :image, accept: 'image/png,image/gif,image/jpeg')
# => <input type="file" id="article_image" name="article[image]" accept="image/png,image/gif,image/jpeg" />
file_field(:attachment, :file, class: 'file_input')
# => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
来源:显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1248 def file_field(object_name, method, options = {}) options = { include_hidden: multiple_file_field_include_hidden }.merge!(options) Tags::FileField.new(object_name, method, self, convert_direct_upload_option_to_url(options.dup)).render end
form_for(record, options = {}, &block) 链接
创建一个表单,允许用户创建或更新特定模型对象的属性。
该方法可以使用几种略微不同的方法,具体取决于您希望在多大程度上依赖 Rails 从模型自动推断表单的构建方式。对于通用模型对象,可以通过向 form_for
传递表示我们关注的对象的字符串或符号来创建表单
<%= form_for :person do |f| %>
First name: <%= f.text_field :first_name %><br />
Last name : <%= f.text_field :last_name %><br />
Biography : <%= f.textarea :biography %><br />
Admin? : <%= f.checkbox :admin %><br />
<%= f.submit %>
<% end %>
传递给代码块的变量 f
是一个 FormBuilder
对象,它包含有关传递给 form_for
的 :person
所表示的模型对象的信息。在 FormBuilder
上定义的方法用于生成绑定到此模型的字段。因此,例如,
<%= f.text_field :first_name %>
将扩展为
<%= text_field :person, :first_name %>
这将生成一个 HTML <input>
标签,其 name
属性为 person[first_name]
。这意味着当提交表单时,用户输入的值将在控制器中可用,为 params[:person][:first_name]
。
对于使用 FormBuilder
以这种方式生成的字段,如果 :person
也恰好是实例变量 @person
的名称,则表单首次显示时显示的字段默认值(例如,在编辑现有记录的情况下)将是 @person
对应属性的值。
form_for
的最右侧参数是一个可选的选项哈希 -
-
:url
- 表单要提交到的 URL。这可以用与传递给url_for
或link_to
的值相同的方式表示。因此,例如,您可以直接使用命名路由。当模型由字符串或符号表示时,如上面的示例所示,如果未指定:url
选项,则默认情况下,表单将发送回当前 URL(我们将在下面描述form_for
的另一种面向资源的用法,其中不需要显式指定 URL)。 -
:namespace
- 表单的命名空间,以确保表单元素上 id 属性的唯一性。命名空间属性将在生成的 HTML id 上以下划线为前缀。 -
:method
- 提交表单时要使用的方法,通常是“get”或“post”。如果使用“patch”、“put”、“delete”或其他动词,则添加一个名为_method
的隐藏输入以模拟对 post 的动词。 -
:authenticity_token
- 表单中要使用的身份验证令牌。仅当您需要传递自定义身份验证令牌字符串或根本不添加身份验证令牌字段(通过传递false
)时才使用。远程表单可以通过设置config.action_view.embed_authenticity_token_in_remote_forms = false
来省略嵌入的身份验证令牌。当您对表单进行片段缓存时,这很有用。远程表单从meta
标签获取身份验证令牌,因此除非您支持没有 JavaScript 的浏览器,否则嵌入是不必要的。 -
:remote
- 如果设置为 true,则将允许 Unobtrusive JavaScript 驱动程序控制提交行为。 -
:enforce_utf8
- 如果设置为 false,则不会输出名为 utf8 的隐藏输入。 -
:html
- 表单标签的可选 HTML 属性。
另请注意,form_for
不会创建排他性作用域。仍然可以使用独立的 FormHelper
方法和来自 FormTagHelper
的方法。例如
<%= form_for :person do |f| %>
First name: <%= f.text_field :first_name %>
Last name : <%= f.text_field :last_name %>
Biography : <%= textarea :person, :biography %>
Admin? : <%= checkbox_tag "person[admin]", "1", @person.company.admin? %>
<%= f.submit %>
<% end %>
这同样适用于 FormOptionsHelper
和 DateHelper
中设计为使用对象作为基准的方法,例如 FormOptionsHelper#collection_select
和 DateHelper#datetime_select
。
form_for
使用模型对象
在上面的示例中,要创建或编辑的对象由传递给 form_for
的符号表示,我们注意到字符串也可以等效地使用。然而,也可以将模型对象本身传递给 form_for
。例如,如果 @article
是要编辑的现有记录,可以使用以下方法创建表单
<%= form_for @article do |f| %>
...
<% end %>
它的行为几乎与之前概述的相同,但也有一些细微的例外。首先,用于在表单中命名输入元素的前缀(因此是表示它们在 params
哈希中的键)实际上是从对象的类派生的,例如 params[:article]
如果对象的类是 Article
。但是,这可以使用 :as
选项覆盖,例如 -
<%= form_for(@person, as: :client) do |f| %>
...
<% end %>
将导致 params[:client]
。
其次,表单初始显示时显示的字段值取自传递给 form_for
的对象的属性,无论对象是否是实例变量。因此,例如,如果我们有一个本地变量 article
代表现有记录,
<%= form_for article do |f| %>
...
<% end %>
将生成一个表单,其字段的初始状态反映了 article
属性的当前值。
面向资源的风格
在刚刚显示的示例中,虽然没有明确说明,但我们仍然需要使用 :url
选项来指定表单将被发送到哪里。然而,如果传递给 form_for
的记录是资源,即它对应一组 RESTful 路由,例如使用 config/routes.rb
中的 resources
方法定义,则可以进一步简化。在这种情况下,Rails 将简单地从记录本身推断出合适的 URL。例如,
<%= form_for @article do |f| %>
...
<% end %>
等效于以下内容
<%= form_for @article, as: :article, url: article_path(@article), method: :patch, html: { class: "edit_article", id: "edit_article_45" } do |f| %>
...
<% end %>
对于新记录
<%= form_for(Article.new) do |f| %>
...
<% end %>
等效于以下内容
<%= form_for @article, as: :article, url: articles_path, html: { class: "new_article", id: "new_article" } do |f| %>
...
<% end %>
但是你仍然可以覆盖单个约定,例如
<%= form_for(@article, url: super_articles_path) do |f| %>
...
<% end %>
可以通过传递 url: false
来省略 action
属性
<%= form_for(@article, url: false) do |f| %>
...
<% end %>
你还可以设置答案格式,如下所示
<%= form_for(@article, format: :json) do |f| %>
...
<% end %>
对于命名空间路由,例如 admin_article_url
<%= form_for([:admin, @article]) do |f| %>
...
<% end %>
如果你的资源定义了关联,例如,你想在文档中添加评论,前提是路由设置正确
<%= form_for([@document, @comment]) do |f| %>
...
<% end %>
其中 @document = Document.find(params[:id])
且 @comment = Comment.new
。
设置方法
你可以通过设置以下选项来强制表单使用完整的 HTTP 动词数组
method: (:get|:post|:patch|:put|:delete)
在 options 哈希中。如果动词不是 GET 或 POST(它们是 HTML 表单原生支持的),则表单将设置为 POST,并且一个名为 _method 的隐藏输入将承载要由服务器解释的预期动词。
非侵入式 JavaScript
指定
remote: true
在 options 哈希中创建允许非侵入式 JavaScript 驱动程序修改其行为的表单。表单提交将与接收方看到的常规提交一样工作(所有元素都可以在 params
中使用)。
示例
<%= form_for(@article, remote: true) do |f| %>
...
<% end %>
为此生成的 HTML 将是
<form action='http://www.example.com' method='post' data-remote='true'>
<input name='_method' type='hidden' value='patch' />
...
</form>
设置 HTML 选项
你可以通过传递一个数据哈希来直接设置数据属性,但所有其他 HTML 选项必须包装在 HTML 键中。示例
<%= form_for(@article, data: { behavior: "autosave" }, html: { name: "go" }) do |f| %>
...
<% end %>
为此生成的 HTML 将是
<form action='http://www.example.com' method='post' data-behavior='autosave' name='go'>
<input name='_method' type='hidden' value='patch' />
...
</form>
删除隐藏的模型 ID
form_for
方法会自动将模型 ID 作为隐藏字段包含在表单中。这用于维护表单数据与其关联模型之间的关联。某些 ORM 系统在嵌套模型上不使用 ID,因此在这种情况下,你希望能够禁用隐藏 ID。
在以下示例中,Article 模型具有许多存储在其内的评论,这些评论存储在 NoSQL 数据库中,因此评论没有主键。
示例
<%= form_for(@article) do |f| %>
<%= f.fields_for(:comments, include_id: false) do |cf| %>
...
<% end %>
<% end %>
自定义表单构建器
你还可以使用自定义 FormBuilder
类构建表单。子类化 FormBuilder
并覆盖或定义更多帮助程序,然后使用你的自定义构建器。例如,假设你创建了一个帮助程序来自动将标签添加到表单输入。
<%= form_for @person, url: { action: "create" }, builder: LabellingFormBuilder do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= f.textarea :biography %>
<%= f.checkbox :admin %>
<%= f.submit %>
<% end %>
在这种情况下,如果你使用
<%= render f %>
渲染的模板是 people/_labelling_form
,引用表单构建器的局部变量称为 labelling_form
。
自定义 FormBuilder
类会自动与嵌套 fields_for
调用的选项合并,除非它被明确设置。
在很多情况下,你可能希望将上述内容包装在另一个帮助程序中,因此你可以执行以下操作
def labelled_form_for(record_or_name_or_array, *args, &block)
options = args.extract_options!
form_for(record_or_name_or_array, *(args << options.merge(builder: LabellingFormBuilder)), &block)
end
如果你不需要将表单附加到模型实例,那么请查看 FormTagHelper#form_tag
。
表单到外部资源
当你构建表单到外部资源时,有时你需要设置一个身份验证令牌或只是渲染一个没有身份验证令牌的表单,例如当你将数据提交到支付网关时,数字和字段类型可能会受到限制。
要设置身份验证令牌,你需要传递一个 :authenticity_token
参数
<%= form_for @invoice, url: external_url, authenticity_token: 'external_token' do |f| %>
...
<% end %>
如果你不希望渲染身份验证令牌字段,只需传递 false
<%= form_for @invoice, url: external_url, authenticity_token: false do |f| %>
...
<% end %>
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 436 def form_for(record, options = {}, &block) raise ArgumentError, "Missing block" unless block_given? case record when String, Symbol model = false object_name = record else model = record object = _object_for_form_builder(record) raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object object_name = options[:as] || model_name_from_record_or_class(object).param_key apply_form_for_options!(object, options) end remote = options.delete(:remote) if remote && !embed_authenticity_token_in_remote_forms && options[:authenticity_token].blank? options[:authenticity_token] = false end options[:model] = model options[:scope] = object_name options[:local] = !remote options[:skip_default_ids] = false options[:allow_method_names_outside_object] = options.fetch(:allow_method_names_outside_object, false) form_with(**options, &block) end
form_with(model: false, scope: nil, url: nil, format: nil, **options, &block) 链接
根据混合 URL、范围或模型创建表单标签。
# Using just a URL:
<%= form_with url: articles_path do |form| %>
<%= form.text_field :title %>
<% end %>
# =>
<form action="/articles" method="post">
<input type="text" name="title" />
</form>
# With an intentionally empty URL:
<%= form_with url: false do |form| %>
<%= form.text_field :title %>
<% end %>
# =>
<form method="post">
<input type="text" name="title" />
</form>
# Adding a scope prefixes the input field names:
<%= form_with scope: :article, url: articles_path do |form| %>
<%= form.text_field :title %>
<% end %>
# =>
<form action="/articles" method="post">
<input type="text" name="article[title]" />
</form>
# Using a model infers both the URL and scope:
<%= form_with model: Article.new do |form| %>
<%= form.text_field :title %>
<% end %>
# =>
<form action="/articles" method="post">
<input type="text" name="article[title]" />
</form>
# An existing model makes an update form and fills out field values:
<%= form_with model: Article.first do |form| %>
<%= form.text_field :title %>
<% end %>
# =>
<form action="/articles/1" method="post">
<input type="hidden" name="_method" value="patch" />
<input type="text" name="article[title]" value="<the title of the article>" />
</form>
# Though the fields don't have to correspond to model attributes:
<%= form_with model: Cat.new do |form| %>
<%= form.text_field :cats_dont_have_gills %>
<%= form.text_field :but_in_forms_they_can %>
<% end %>
# =>
<form action="/cats" method="post">
<input type="text" name="cat[cats_dont_have_gills]" />
<input type="text" name="cat[but_in_forms_they_can]" />
</form>
表单中的参数根据其名称嵌套在控制器中访问。因此,名为 title
和 article[title]
的输入分别可作为 params[:title]
和 params[:article][:title]
访问。
为了便于比较,上面的示例省略了提交按钮,以及启用 UTF-8 支持并添加身份验证令牌的自动生成隐藏字段,该身份验证令牌对于跨站点请求伪造保护是必需的。
面向资源的风格
在刚刚显示的许多示例中,传递给 form_with
的 :model
是一个资源。它对应一组 RESTful 路由,很可能通过 config/routes.rb
中的 resources
定义。
因此,当传递这样的模型记录时,Rails 会推断出 URL 和方法。
<%= form_with model: @article do |form| %>
...
<% end %>
等效于以下内容
<%= form_with scope: :article, url: article_path(@article), method: :patch do |form| %>
...
<% end %>
对于新记录
<%= form_with model: Article.new do |form| %>
...
<% end %>
等效于以下内容
<%= form_with scope: :article, url: articles_path do |form| %>
...
<% end %>
form_with
选项
-
:url
- 表单提交到的 URL。类似于传递给url_for
或link_to
的值。例如,你可以直接使用命名路由。当传递:scope
但没有传递:url
时,表单只会提交到当前 URL。 -
:method
- 提交表单时使用的 HTTP 方法,通常是“get”或“post”。如果使用“patch”、“put”、“delete”或其他动词,则会添加一个名为_method
的隐藏输入来模拟通过 post 的动词。 -
:format
- 表单提交到的路由的格式。当提交到其他资源类型时很有用,例如:json
。如果传递了:url
,则跳过此选项。 -
:scope
- 要用作输入字段名称前缀的范围,以及提交的参数如何在控制器中分组。 -
:namespace
- 表单的命名空间,以确保表单元素上 id 属性的唯一性。命名空间属性将在生成的 HTML id 上以下划线为前缀。 -
:model
- 一个模型对象,用于推断:url
和:scope
,以及填充输入字段值。因此,如果title
属性设置为“Ahoy!”,则title
输入字段的值将为“Ahoy!”。如果模型是新记录,则会生成创建表单,如果模型是现有记录,则会生成更新表单。传递:scope
或:url
来覆盖默认值。例如,将params[:article]
转换为params[:blog]
。 -
:authenticity_token
- 在表单中使用的身份验证令牌。使用自定义身份验证令牌覆盖它,或者传递false
来完全跳过身份验证令牌字段。当提交到外部资源(如可能限制有效字段的支付网关)时很有用。远程表单可以通过设置config.action_view.embed_authenticity_token_in_remote_forms = false
来省略嵌入式身份验证令牌。当片段缓存表单时,这很有用。远程表单从meta
标签获取身份验证令牌,因此除非支持没有 JavaScript 的浏览器,否则嵌入是多余的。 -
:local
- 是否使用标准 HTTP 表单提交。设置为true
时,表单通过标准 HTTP 提交。设置为false
时,表单作为“远程表单”提交,由 Rails UJS 作为 XHR 处理。未指定时,行为来自config.action_view.form_with_generates_remote_forms
,其中配置的值实际上是local
值的倒数。从 Rails 6.1 开始,该配置选项默认为false
(与传递local: true
的效果相同)。在 Rails 的先前版本中,该配置选项默认为true
(与传递local: false
的效果相同)。 -
:skip_enforcing_utf8
- 如果设置为 true,则不会输出名为 utf8 的隐藏输入。 -
:builder
- 覆盖用于构建表单的对象。 -
:id
- 可选的 HTML id 属性。 -
:class
- 可选的 HTML class 属性。 -
:data
- 可选的 HTML 数据属性。 -
:html
- 表单标签的其他可选 HTML 属性。
示例
不传递块时,form_with
只会生成一个开头的表单标签。
<%= form_with(model: @article, url: super_articles_path) %>
<%= form_with(model: @article, scope: :blog) %>
<%= form_with(model: @article, format: :json) %>
<%= form_with(model: @article, authenticity_token: false) %> # Disables the token.
对于命名空间路由,例如 admin_article_url
<%= form_with(model: [ :admin, @article ]) do |form| %>
...
<% end %>
如果你的资源定义了关联,例如,你想在文档中添加评论,前提是路由设置正确
<%= form_with(model: [ @document, Comment.new ]) do |form| %>
...
<% end %>
其中 @document = Document.find(params[:id])
。
与其他表单助手混合使用
虽然 form_with
使用 FormBuilder
对象,但您可以混合使用独立的 FormHelper
方法和 FormTagHelper 中的方法
<%= form_with scope: :person do |form| %>
<%= form.text_field :first_name %>
<%= form.text_field :last_name %>
<%= textarea :person, :biography %>
<%= checkbox_tag "person[admin]", "1", @person.company.admin? %>
<%= form.submit %>
<% end %>
对于旨在使用对象作为基础的 FormOptionsHelper
和 DateHelper
中的方法也是如此,例如 FormOptionsHelper#collection_select
和 DateHelper#datetime_select
。
设置方法
你可以通过设置以下选项来强制表单使用完整的 HTTP 动词数组
method: (:get|:post|:patch|:put|:delete)
在 options 哈希中。如果动词不是 GET 或 POST(它们是 HTML 表单原生支持的),则表单将设置为 POST,并且一个名为 _method 的隐藏输入将承载要由服务器解释的预期动词。
设置 HTML 选项
你可以直接在数据哈希中设置数据属性,但除 id 和 class 之外的 HTML 选项必须包装在 HTML 键中
<%= form_with(model: @article, data: { behavior: "autosave" }, html: { name: "go" }) do |form| %>
...
<% end %>
生成
<form action="/articles/123" method="post" data-behavior="autosave" name="go">
<input name="_method" type="hidden" value="patch" />
...
</form>
删除隐藏的模型 ID
form_with
方法会自动将模型 ID 作为隐藏字段包含在表单中。这用于维护表单数据与其关联模型之间的关联。某些 ORM 系统在嵌套模型上不使用 ID,因此在这种情况下,你希望能够禁用隐藏 ID。
在以下示例中,Article 模型具有许多存储在其内的评论,这些评论存储在 NoSQL 数据库中,因此评论没有主键。
<%= form_with(model: @article) do |form| %>
<%= form.fields(:comments, skip_id: true) do |fields| %>
...
<% end %>
<% end %>
自定义表单构建器
你还可以使用自定义 FormBuilder
类构建表单。子类化 FormBuilder
并覆盖或定义更多帮助程序,然后使用你的自定义构建器。例如,假设你创建了一个帮助程序来自动将标签添加到表单输入。
<%= form_with model: @person, url: { action: "create" }, builder: LabellingFormBuilder do |form| %>
<%= form.text_field :first_name %>
<%= form.text_field :last_name %>
<%= form.textarea :biography %>
<%= form.checkbox :admin %>
<%= form.submit %>
<% end %>
在这种情况下,如果你使用
<%= render form %>
渲染的模板是 people/_labelling_form
,引用表单构建器的局部变量称为 labelling_form
。
自定义 FormBuilder
类会自动与嵌套 fields
调用的选项合并,除非它被明确设置。
在很多情况下,你可能希望将上述内容包装在另一个帮助程序中,因此你可以执行以下操作
def labelled_form_with(**options, &block)
form_with(**options.merge(builder: LabellingFormBuilder), &block)
end
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 756 def form_with(model: false, scope: nil, url: nil, format: nil, **options, &block) raise ArgumentError, "Passed nil to the :model argument, expect an object or false" if model.nil? options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options) if model if url != false url ||= if format.nil? polymorphic_path(model, {}) else polymorphic_path(model, format: format) end end model = convert_to_model(_object_for_form_builder(model)) scope ||= model_name_from_record_or_class(model).param_key end if block_given? builder = instantiate_builder(scope, model, options) output = capture(builder, &block) options[:multipart] ||= builder.multipart? html_options = html_options_for_form_with(url, model, **options) form_tag_with_body(html_options, output) else html_options = html_options_for_form_with(url, model, **options) form_tag_html(html_options) end end
hidden_field(object_name, method, options = {}) 链接
返回一个隐藏的输入标签,用于访问模板对象(由object
标识)中指定属性(由method
标识)。 可以使用options
中的哈希表传递输入标签的额外选项。 这些选项将作为 HTML 元素属性标记到 HTML 中,如示例所示。
示例
hidden_field(:signup, :pass_confirm)
# => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="#{@signup.pass_confirm}" />
hidden_field(:article, :tag_list)
# => <input type="hidden" id="article_tag_list" name="article[tag_list]" value="#{@article.tag_list}" />
hidden_field(:user, :token)
# => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />
源代码: 在 GitHub 上
|label(object_name, method, content_or_options = nil, options = nil, &block) 链接
返回一个标签标签,用于标记模板对象(由object
标识)中指定属性(由method
标识)的输入字段。 标签的文本默认情况下将为属性名称,除非在当前 I18n 本地化中找到翻译(通过helpers.label.<modelname>.<attribute>
)或显式指定它。 可以使用options
中的哈希表传递标签标签的额外选项。 这些选项将作为 HTML 元素属性标记到 HTML 中,如示例所示,除了:value
选项,该选项旨在针对radio_button
标签(其中 value 用于输入标签的 ID 中)。
示例
label(:article, :title)
# => <label for="article_title">Title</label>
您可以根据模型和属性名称对标签进行本地化。 例如,您可以在您的本地化文件(例如 en.yml)中定义以下内容:
helpers:
label:
article:
body: "Write your entire text here"
这将导致以下结果:
label(:article, :body)
# => <label for="article_body">Write your entire text here</label>
本地化也可以纯粹基于属性名称的翻译(如果您使用的是ActiveRecord
)。
activerecord:
attributes:
article:
cost: "Total cost"
label(:article, :cost)
# => <label for="article_cost">Total cost</label>
label(:article, :title, "A short title")
# => <label for="article_title">A short title</label>
label(:article, :title, "A short title", class: "title_label")
# => <label for="article_title" class="title_label">A short title</label>
label(:article, :privacy, "Public Article", value: "public")
# => <label for="article_privacy_public">Public Article</label>
label(:article, :cost) do |translation|
content_tag(:span, translation, class: "cost_label")
end
# => <label for="article_cost"><span class="cost_label">Total cost</span></label>
label(:article, :cost) do |builder|
content_tag(:span, builder.translation, class: "cost_label")
end
# => <label for="article_cost"><span class="cost_label">Total cost</span></label>
label(:article, :terms) do
raw('Accept <a href="/terms">Terms</a>.')
end
# => <label for="article_terms">Accept <a href="/terms">Terms</a>.</label>
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1152 def label(object_name, method, content_or_options = nil, options = nil, &block) Tags::Label.new(object_name, method, self, content_or_options, options).render(&block) end
month_field(object_name, method, options = {}) 链接
返回一个类型为“month”的text_field
。
month_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="month" />
默认值是通过尝试在对象的 value 上使用“%Y-%m”调用strftime
生成的,这使得它在DateTime
和ActiveSupport::TimeWithZone
的实例中按预期工作。
@user.born_on = Date.new(1984, 1, 27)
month_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-01" />
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1534 def month_field(object_name, method, options = {}) Tags::MonthField.new(object_name, method, self, options).render end
number_field(object_name, method, options = {}) 链接
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1578 def number_field(object_name, method, options = {}) Tags::NumberField.new(object_name, method, self, options).render end
password_field(object_name, method, options = {}) 链接
返回一个类型为“password”的输入标签,用于访问模板对象(由object
标识)中指定属性(由method
标识)。 可以使用options
中的哈希表传递输入标签的额外选项。 这些选项将作为 HTML 元素属性标记到 HTML 中,如示例所示。 出于安全原因,此字段默认情况下为空; 如果不需要,请通过options
传递一个值。
示例
password_field(:login, :pass, size: 20)
# => <input type="password" id="login_pass" name="login[pass]" size="20" />
password_field(:account, :secret, class: "form_input", value: @account.secret)
# => <input type="password" id="account_secret" name="account[secret]" value="#{@account.secret}" class="form_input" />
password_field(:user, :password, onchange: "if ($('#user_password').val().length > 30) { alert('Your password needs to be shorter!'); }")
# => <input type="password" id="user_password" name="user[password]" onchange="if ($('#user_password').val().length > 30) { alert('Your password needs to be shorter!'); }"/>
password_field(:account, :pin, size: 20, class: 'form_input')
# => <input type="password" id="account_pin" name="account[pin]" size="20" class="form_input" />
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1197 def password_field(object_name, method, options = {}) Tags::PasswordField.new(object_name, method, self, options).render end
radio_button(object_name, method, tag_value, options = {}) 链接
返回一个单选按钮标签,用于访问模板对象(由object
标识)中指定属性(由method
标识)。 如果method
的当前值为tag_value
,则单选按钮将被选中。
要强制选中单选按钮,请在options
哈希表中传递checked: true
。 您也可以在其中传递 HTML 选项。
# Let's say that @article.category returns "rails":
radio_button("article", "category", "rails")
radio_button("article", "category", "java")
# => <input type="radio" id="article_category_rails" name="article[category]" value="rails" checked="checked" />
# <input type="radio" id="article_category_java" name="article[category]" value="java" />
# Let's say that @user.receive_newsletter returns "no":
radio_button("user", "receive_newsletter", "yes")
radio_button("user", "receive_newsletter", "no")
# => <input type="radio" id="user_receive_newsletter_yes" name="user[receive_newsletter]" value="yes" />
# <input type="radio" id="user_receive_newsletter_no" name="user[receive_newsletter]" value="no" checked="checked" />
源代码: 显示 | 在 GitHub 上
range_field(object_name, method, options = {}) 链接
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1587 def range_field(object_name, method, options = {}) Tags::RangeField.new(object_name, method, self, options).render end
rich_textarea(object_name, method, options = {}) 链接
返回一个trix-editor
标签,该标签会实例化 Trix JavaScript 编辑器,以及一个隐藏字段,Trix 会在更改时写入该字段,以便内容会在表单提交时发送。
选项
-
:class
- 默认值为“trix-content”,确保应用默认样式。 -
:value
- 在 HTML 输入标签中添加默认值。 -
[:data][:direct_upload_url]
- 默认值为rails_direct_uploads_url
。 -
[:data][:blob_url_template]
- 默认值为rails_service_blob_url(":signed_id", ":filename")
。
示例
rich_textarea :message, :content
# <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
# <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
rich_textarea :message, :content, value: "<h1>Default message</h1>"
# <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="<h1>Default message</h1>">
# <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
源代码: 显示 | 在 GitHub 上
# File actiontext/app/helpers/action_text/tag_helper.rb, line 87 def rich_textarea(object_name, method, options = {}) Tags::ActionText.new(object_name, method, self, options).render end
search_field(object_name, method, options = {}) 链接
返回一个类型为“search”的输入,用于访问模板对象(由object_name
标识)中指定属性(由method
标识)。 类型为“search”的输入可能被某些浏览器以不同的方式进行样式设置。
search_field(:user, :name)
# => <input id="user_name" name="user[name]" type="search" />
search_field(:user, :name, autosave: false)
# => <input autosave="false" id="user_name" name="user[name]" type="search" />
search_field(:user, :name, results: 3)
# => <input id="user_name" name="user[name]" results="3" type="search" />
# Assume request.host returns "www.example.com"
search_field(:user, :name, autosave: true)
# => <input autosave="com.example.www" id="user_name" name="user[name]" results="10" type="search" />
search_field(:user, :name, onsearch: true)
# => <input id="user_name" incremental="true" name="user[name]" onsearch="true" type="search" />
search_field(:user, :name, autosave: false, onsearch: true)
# => <input autosave="false" id="user_name" incremental="true" name="user[name]" onsearch="true" type="search" />
search_field(:user, :name, autosave: true, onsearch: true)
# => <input autosave="com.example.www" id="user_name" incremental="true" name="user[name]" onsearch="true" results="10" type="search" />
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1401 def search_field(object_name, method, options = {}) Tags::SearchField.new(object_name, method, self, options).render end
telephone_field(object_name, method, options = {}) 链接
返回一个类型为“tel”的text_field
。
telephone_field("user", "phone")
# => <input id="user_phone" name="user[phone]" type="tel" />
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1410 def telephone_field(object_name, method, options = {}) Tags::TelField.new(object_name, method, self, options).render end
text_field(object_name, method, options = {}) 链接
返回一个类型为“text”的输入标签,用于访问模板对象(由object
标识)中指定属性(由method
标识)。 可以使用options
中的哈希表传递输入标签的额外选项。 这些选项将作为 HTML 元素属性标记到 HTML 中,如示例所示。
示例
text_field(:article, :title, size: 20)
# => <input type="text" id="article_title" name="article[title]" size="20" value="#{@article.title}" />
text_field(:article, :title, class: "create_input")
# => <input type="text" id="article_title" name="article[title]" value="#{@article.title}" class="create_input" />
text_field(:article, :title, maxlength: 30, class: "title_input")
# => <input type="text" id="article_title" name="article[title]" maxlength="30" size="30" value="#{@article.title}" class="title_input" />
text_field(:session, :user, onchange: "if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }")
# => <input type="text" id="session_user" name="session[user]" value="#{@session.user}" onchange="if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }"/>
text_field(:snippet, :code, size: 20, class: 'code_input')
# => <input type="text" id="snippet_code" name="snippet[code]" size="20" value="#{@snippet.code}" class="code_input" />
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1176 def text_field(object_name, method, options = {}) Tags::TextField.new(object_name, method, self, options).render end
textarea(object_name, method, options = {}) 链接
返回一个文本区域的开头和结尾标签集,用于访问模板对象(由object
标识)中指定属性(由method
标识)。 可以使用options
中的哈希表传递输入标签的额外选项。
示例
textarea(:article, :body, cols: 20, rows: 40)
# => <textarea cols="20" rows="40" id="article_body" name="article[body]">
# #{@article.body}
# </textarea>
textarea(:comment, :text, size: "20x30")
# => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
# #{@comment.text}
# </textarea>
textarea(:application, :notes, cols: 40, rows: 15, class: 'app_input')
# => <textarea cols="40" rows="15" id="application_notes" name="application[notes]" class="app_input">
# #{@application.notes}
# </textarea>
textarea(:entry, :body, size: "20x20", disabled: 'disabled')
# => <textarea cols="20" rows="20" id="entry_body" name="entry[body]" disabled="disabled">
# #{@entry.body}
# </textarea>
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1278 def textarea(object_name, method, options = {}) Tags::TextArea.new(object_name, method, self, options).render end
time_field(object_name, method, options = {}) 链接
返回一个类型为“time”的text_field
。
默认值是通过尝试在对象的 value 上使用“%T.%L”调用strftime
生成的。 如果您传递include_seconds: false
,它将通过尝试在对象的 value 上使用“%H:%M”调用strftime
来进行格式化。 您也可以通过传递“value”选项来覆盖它。
选项
支持与FormTagHelper#time_field_tag
相同的选项。
示例
time_field("task", "started_at")
# => <input id="task_started_at" name="task[started_at]" type="time" />
您可以通过将 Date
或 Time
的实例传递给选项哈希来创建“min”和“max”属性的值。
time_field("task", "started_at", min: Time.now)
# => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />
或者,您可以将格式化为 ISO8601 时间的String
作为“min”和“max”的值传递。
time_field("task", "started_at", min: "01:00:00")
# => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />
默认情况下,提供的時間將會包含秒數進行格式化。 您可以在時間戳格式中通過传递include_seconds: false
来只渲染小時和分钟。 如果您在時間戳格式中排除秒數,一些瀏覽器將呈現更簡單的 UI。
time_field("task", "started_at", value: Time.now, include_seconds: false)
# => <input id="task_started_at" name="task[started_at]" type="time" value="01:00" />
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1480 def time_field(object_name, method, options = {}) Tags::TimeField.new(object_name, method, self, options).render end
url_field(object_name, method, options = {}) 链接
返回一个类型为“url”的text_field
。
url_field("user", "homepage")
# => <input id="user_homepage" name="user[homepage]" type="url" />
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1560 def url_field(object_name, method, options = {}) Tags::UrlField.new(object_name, method, self, options).render end
week_field(object_name, method, options = {}) 链接
返回一个类型为“week”的 text_field
。
week_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="week" />
默认值是通过尝试使用“%Y-W%W”对对象的 value 调用 strftime
生成的,这使得它在 DateTime
和 ActiveSupport::TimeWithZone
实例中按预期工作。
@user.born_on = Date.new(1984, 5, 12)
week_field("user", "born_on")
# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-W19" />
源代码: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/form_helper.rb, line 1551 def week_field(object_name, method, options = {}) Tags::WeekField.new(object_name, method, self, options).render end