如何自定义表单渲染
Symfony 为您提供了几种自定义表单渲染方式。在本文中,您将学习如何对表单的一个或多个字段进行单项自定义。如果您需要以相同的方式自定义所有表单,请创建一个表单主题或使用任何内置主题,例如 Symfony 表单的 Bootstrap 主题。
表单渲染函数
只需调用一次 form() Twig 函数,即可渲染整个表单,包括所有字段和错误消息
1 2 3 4
{# form is a variable passed from the controller via
$this->render('...', ['form' => $form])
or $this->render('...', ['form' => $form->createView()]) #}
{{ form(form) }}
下一步是使用 form_start()、form_end()、form_errors() 和 form_row() Twig 函数渲染不同的表单部分,以便您可以自定义它们,添加 HTML 元素和属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14
{{ form_start(form) }}
<div class="my-custom-class-for-errors">
{{ form_errors(form) }}
</div>
<div class="row">
<div class="col">
{{ form_row(form.task) }}
</div>
<div class="col" id="some-custom-id">
{{ form_row(form.dueDate) }}
</div>
</div>
{{ form_end(form) }}
form_row()
函数输出整个字段内容,包括标签、帮助消息、HTML 元素和错误消息。所有这些都可以使用其他 Twig 函数进一步自定义,如下图所示
form_label()、form_widget()(HTML 输入)、form_help() 和 form_errors() Twig 函数使您可以完全控制每个表单字段的渲染方式,因此您可以完全自定义它们
1 2 3 4 5 6 7 8 9 10
<div class="form-control">
<i class="fa fa-calendar"></i> {{ form_label(form.dueDate) }}
{{ form_widget(form.dueDate) }}
<small>{{ form_help(form.dueDate) }}</small>
<div class="form-error">
{{ form_errors(form.dueDate) }}
</div>
</div>
警告
如果您正在手动渲染每个字段,请确保不要忘记自动添加的 _token
字段,以实现 CSRF 保护。
您还可以使用 {{ form_rest(form) }}
(推荐)来渲染任何未手动渲染的字段。有关更多信息,请参阅下文的 form_rest() 文档。
注意
本文稍后部分,您可以找到这些 Twig 函数的完整参考以及更多用法示例。
表单字段助手
上一节中显示的 form_*()
助手渲染表单字段的不同部分,包括其所有 HTML 元素。一些开发人员和设计师对这种行为感到困惑,因为它将所有 HTML 元素隐藏在表单主题中,而表单主题的自定义并非易事。
这就是 Symfony 提供其他 Twig 表单助手的原因,这些助手渲染每个表单字段部分的值,而不添加任何 HTML 包装
field_name()
field_value()
field_label()
field_help()
field_errors()
field_choices()
(选择字段的迭代器;例如,用于<select>
)
使用这些助手时,您必须为所有表单字段编写所有 HTML 内容,因此您不再需要处理表单主题
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<input
name="{{ field_name(form.username) }}"
value="{{ field_value(form.username) }}"
placeholder="{{ field_label(form.username) }}"
class="form-control"
>
<select name="{{ field_name(form.country) }}" class="form-control">
<option value="">{{ field_label(form.country) }}</option>
{% for label, value in field_choices(form.country) %}
<option value="{{ value }}">{{ label }}</option>
{% endfor %}
</select>
表单渲染变量
上一节中提到的一些 Twig 函数允许传递变量来配置其行为。例如,form_label()
函数允许您定义自定义标签以覆盖表单中定义的标签
1
{{ form_label(form.task, 'My Custom Task Label') }}
某些 表单字段类型 具有可以传递给小部件的其他渲染选项。这些选项在每种类型中都有文档记录,但一个常见的选项是 attr
,它允许您修改表单元素上的 HTML 属性。以下代码会将 task_field
CSS 类添加到渲染的输入文本字段中
1
{{ form_widget(form.task, {'attr': {'class': 'task_field'}}) }}
注意
如果您一次渲染整个表单(或整个嵌入式表单),则 variables
参数将仅应用于表单本身,而不应用于其子表单。换句话说,以下代码不会将 "foo" 类属性传递给表单中的所有子字段
1 2
{# does **not** work - the variables are not recursive #}
{{ form_widget(form, { 'attr': {'class': 'foo'} }) }}
如果您需要“手动”渲染表单字段,则可以使用其 vars
属性访问字段的各个值(例如 id
、name
和 label
)。例如,要获取 id
1
{{ form.task.vars.id }}
注意
本文稍后部分,您可以找到这些 Twig 变量的完整参考及其描述。
表单主题
前面几节中显示的 Twig 函数和变量可以帮助您自定义表单的一个或多个字段。但是,此自定义无法应用于应用程序的其余表单。
如果您想以相同的方式自定义所有表单(例如,使生成的 HTML 代码适应应用程序中使用的 CSS 框架),则必须创建表单主题。
表单函数和变量参考
函数
form(form_view, variables)
渲染完整表单的 HTML。
1 2
{# render the form and change the submission method #}
{{ form(form, {'method': 'GET'}) }}
您通常会在原型设计或使用自定义表单主题时使用此助手。如果您需要在渲染表单时具有更高的灵活性,则应使用其他助手来渲染表单的各个部分
1 2 3 4 5 6 7 8
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.name) }}
{{ form_row(form.dueDate) }}
{{ form_row(form.submit, { 'label': 'Submit me' }) }}
{{ form_end(form) }}
form_start(form_view, variables)
渲染表单的开始标记。此助手负责打印表单的配置方法和目标操作。如果表单包含上传字段,它还将包含正确的 enctype
属性。
1 2
{# render the start tag and change the submission method #}
{{ form_start(form, {'method': 'GET'}) }}
form_end(form_view, variables)
渲染表单的结束标记。
1
{{ form_end(form) }}
除非您将 render_rest
设置为 false,否则此助手还会输出 form_rest()
(本文稍后会对此进行解释)
1 2
{# don't render unrendered fields #}
{{ form_end(form, {render_rest: false}) }}
form_label(form_view, label, variables)
渲染给定字段的标签。您可以选择传递要作为第二个参数显示的特定标签。
1 2 3 4 5 6 7 8 9
{{ form_label(form.name) }}
{# The two following syntaxes are equivalent #}
{{ form_label(form.name, 'Your Name', {'label_attr': {'class': 'foo'}}) }}
{{ form_label(form.name, null, {
'label': 'Your name',
'label_attr': {'class': 'foo'}
}) }}
请参阅“如何自定义表单渲染”以了解有关 variables
参数的信息。
form_errors(form_view)
渲染给定字段的任何错误。
1 2 3 4 5
{# render only the error messages related to this field #}
{{ form_errors(form.name) }}
{# render any "global" errors not associated to any form field #}
{{ form_errors(form) }}
警告
在 Bootstrap 4 表单主题中,form_errors()
已包含在 form_label()
中。有关详细信息,请阅读 Bootstrap 4 主题文档。
form_widget(form_view, variables)
渲染给定字段的 HTML 小部件。如果您将其应用于整个表单或字段集合,则将渲染每个基础表单行。
1 2
{# render a widget, but add a "foo" class to it #}
{{ form_widget(form.name, {'attr': {'class': 'foo'}}) }}
form_widget()
的第二个参数是变量数组。最常见的变量是 attr
,它是应用于 HTML 小部件的 HTML 属性数组。在某些情况下,某些类型还具有可以传递的其他与模板相关的选项。这些将在类型的基础上进行讨论。如果您一次渲染多个字段(例如 form_widget(form)
),则 attributes
不会递归地应用于子字段。
请参阅“如何自定义表单渲染”以了解有关 variables
参数的更多信息。
form_row(form_view, variables)
渲染给定字段的“行”,它是字段的标签、错误、帮助和部件的组合。
1 2
{# render a field row, but display a label with text "foo" #}
{{ form_row(form.name, {'label': 'foo'}) }}
form_row()
的第二个参数是变量数组。Symfony 中提供的模板仅允许覆盖标签,如上面的示例所示。
请参阅“如何自定义表单渲染”以了解有关 variables
参数的信息。
form_rest(form_view, variables)
这会渲染给定表单中尚未渲染的所有字段。最好始终在表单中的某个位置包含此内容,因为它会为您渲染隐藏字段,并使您更容易发现忘记渲染的任何字段(因为它会为您渲染该字段)。
1
{{ form_rest(form) }}
form_parent(form_view)
如果表单视图已经是根表单,则返回父表单视图或 null
。应优先使用此函数来访问父表单,而不是使用 form.parent
访问父表单。当子表单命名为 parent
时,后一种方法会产生不同的结果。
测试
可以通过在 Twig 中使用 is
运算符来创建条件来执行测试。有关更多信息,请阅读 Twig 文档。
selectedchoice(selected_value)
此测试将检查当前选择是否等于 selected_value
,或者当前选择是否在数组中(当 selected_value
是数组时)。
1
<option {% if choice is selectedchoice(value) %}selected="selected"{% endif %}>
rootform
此测试将检查当前 form
是否没有父表单视图。
1 2 3 4 5 6 7 8 9 10 11 12
{# DON'T DO THIS: this simple check can't differentiate between a form having
a parent form view and a form defining a nested form field called 'parent' #}
{% if form.parent is null %}
{{ form_errors(form) }}
{% endif %}
{# DO THIS: this check is always reliable, even if the form defines a field called 'parent' #}
{% if form is rootform %}
{{ form_errors(form) }}
{% endif %}
表单变量参考
以下变量是每种字段类型通用的。某些字段类型可能定义更多变量,并且此处的一些变量实际上仅适用于某些类型。要了解每种类型可用的确切变量,请查看您的表单主题使用的模板代码。
假设您的模板中有一个 form
变量,并且您想引用 name
字段上的变量,则可以通过使用 FormView 对象上的公共 vars
属性来访问变量
1 2 3 4
<label for="{{ form.name.vars.id }}"
class="{{ form.name.vars.required ? 'required' }}">
{{ form.name.vars.label }}
</label>
变量 | 用法 |
---|---|
action |
当前表单的操作。 |
attr |
将作为字段的 HTML 属性渲染的键值数组。 |
block_prefixes |
父类型的所有名称的数组。 |
cache_key |
用于缓存的唯一键。 |
compound |
字段是否实际上是子字段组的持有者(例如,choice 字段,它实际上是一组复选框)。 |
data |
类型的规范化数据。 |
disabled |
如果 true ,则将 disabled="disabled" 添加到字段。 |
errors |
附加到此特定字段的任何错误的数组(例如,form.title.errors )。请注意,您不能使用 form.errors 来确定表单是否有效,因为这仅返回“全局”错误:某些单个字段可能存在错误。而是使用 valid 选项。 |
form |
当前的 FormView 实例。 |
full_name |
要渲染的 name HTML 属性。 |
help |
将要渲染的帮助消息。 |
id |
要渲染的 id HTML 属性。 |
label |
将要渲染的字符串标签。 |
label_attr |
将作为标签的 HTML 属性渲染的键值数组。 |
method |
当前表单的方法 (POST, GET 等)。 |
multipart |
如果 true ,则 form_enctype 将渲染 enctype="multipart/form-data" 。 |
name |
字段的名称(例如 title ) - 但不是 name HTML 属性,它是 full_name 。 |
required |
如果 true ,则将 required 属性添加到字段以激活 HTML5 验证。此外,还会将 required 类添加到标签。 |
submitted |
根据整个表单是否已提交,返回 true 或 false |
translation_domain |
此表单的翻译域。 |
valid |
根据整个表单是否有效,返回 true 或 false 。 |
value |
渲染时将使用的值(通常是 value HTML 属性)。这仅适用于根表单元素。 |
提示
在幕后,当 Form 组件在表单树的每个“节点”上调用 buildView()
和 finishView()
时,这些变量会提供给表单的 FormView
对象。要查看特定字段具有哪些“视图”变量,请查找表单字段(及其父字段)的源代码,并查看上述两个函数。