跳到內容

如何自訂表單呈現方式

編輯此頁

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>

警告

如果您正在手動呈現每個欄位,請確保您沒有忘記自動新增以進行 CSRF 保護的 _token 欄位。

您也可以使用 {{ 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') }}

某些表單欄位類型具有可以傳遞到 widget 的其他呈現選項。這些選項在每個類型的文件中都有說明,但一個常見的選項是 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 屬性存取欄位的個別值 (例如 idnamelabel)。例如,若要取得 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) }}

此輔助函數也會輸出 form_rest() (稍後將在本文中說明),除非您將 render_rest 設定為 false

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_help(form_view)

呈現給定欄位的輔助文字。

1
{{ form_help(form.name) }}

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 widget。如果您將其套用至整個表單或欄位集合,將會呈現每個基礎表單列。

1
2
{# render a widget, but add a "foo" class to it #}
{{ form_widget(form.name, {'attr': {'class': 'foo'}}) }}

form_widget() 的第二個引數是變數陣列。最常見的變數是 attr,它是要套用至 HTML widget 的 HTML 屬性陣列。在某些情況下,某些類型也有其他可以傳遞的範本相關選項。這些將在類型基礎上進行討論。如果您一次呈現許多欄位 (例如 form_widget(form)),則 attributes 不會遞迴套用至子欄位。

請參閱「如何自訂表單呈現方式」以瞭解有關 variables 引數的更多資訊。

form_row(form_view, variables)

呈現給定欄位的「列」,它是欄位的標籤、錯誤、輔助和 widget 的組合。

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 傳回 truefalse,具體取決於是否已提交整個表單
translation_domain 此表單翻譯的網域。
valid 傳回 truefalse,具體取決於整個表單是否有效。
value 呈現時將使用的值 (通常是 value HTML 屬性)。這僅適用於根表單元素。

提示

在幕後,當 Form 元件在表單樹狀結構的每個「節點」上呼叫 buildView()finishView() 時,這些變數會提供給表單的 FormView 物件。若要查看特定欄位有哪些「檢視」變數,請尋找表單欄位的原始碼 (及其父欄位),並查看上述兩個函數。

此作品,包括程式碼範例,均根據 Creative Commons BY-SA 3.0 授權條款授權。
TOC
    版本