Skip to content

Commit 3bf21e6

Browse files
committed
added the form Twig chapter
1 parent 754dbd6 commit 3bf21e6

File tree

1 file changed

+337
-0
lines changed

1 file changed

+337
-0
lines changed

guides/forms_twig.rst

Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
Forms in Twig Templates
2+
=======================
3+
4+
.. caution::
5+
6+
This chapter describes a feature that is only available in the
7+
``fields_as_templates`` `branch`_.
8+
9+
A Symfony2 :doc:`Form </guides/forms>` is made of fields. Fields describe the
10+
form semantic, not its end-user representation; it means that a form is not
11+
tied to HTML. Instead, it is the responsibility of the web designer to display
12+
each form field the way he wants. So, displaying a Symfony2 form in a template
13+
can easily be done manually. But, Twig eases form integration and
14+
customization by providing a set of filters that can be applied on the form
15+
and field instances.
16+
17+
Displaying a Form
18+
-----------------
19+
20+
As the global structure of a form (the form tag, the submit button, ...) is
21+
not defined by the form instance, you are free to use the HTML code you want.
22+
A simple form template reads as follows:
23+
24+
.. code-block:: html
25+
26+
<form action="#" method="post">
27+
<!-- Display the form fields -->
28+
29+
<input type="submit" />
30+
</form>
31+
32+
Besides the global form structure, you need a way to display global errors and
33+
hidden fields; that's the job of the ``render_errors`` and ``render_hidden``
34+
filters respectively:
35+
36+
.. code-block:: jinja
37+
38+
<form action="#" method="post">
39+
{{ form|render_errors }}
40+
41+
<!-- Display the form fields -->
42+
43+
{{ form|render_hidden }}
44+
<input type="submit" />
45+
</form>
46+
47+
.. note::
48+
By default, the ``render_errors`` generates a ``<ul>`` list, but this can
49+
be easily customized as you will see later in this document.
50+
51+
Last but not the least, a form containing a file input must contain the
52+
``enctype`` attribute; use the ``render_enctype`` filter to render it:
53+
54+
.. code-block:: jinja
55+
56+
<form action="#" {{ form|render_enctype }} method="post">
57+
58+
Displaying Fields
59+
-----------------
60+
61+
Accessing form fields is easy as a Symfony2 form acts as an array:
62+
63+
.. code-block:: jinja
64+
65+
{{ form.title }}
66+
67+
{# access a field (first_name) nested in a group (user) #}
68+
{{ form.user.first_name }}
69+
70+
As each field is a Field instance, it cannot be displayed as show above; use
71+
one of the field filters instead.
72+
73+
The ``render_widget`` filter renders the HTML representation of a field:
74+
75+
.. code-block:: jinja
76+
77+
{{ form.title|render_widget }}
78+
79+
.. note::
80+
The field's widget is selected based on the field class name (more
81+
information below).
82+
83+
The ``render_label`` renders the ``<label>`` tag associated with the field:
84+
85+
.. code-block:: jinja
86+
87+
{{ form.title|render_label }}
88+
89+
By default, Symfony2 "humanizes" the field name, but you can give your own
90+
label:
91+
92+
.. code-block:: jinja
93+
94+
{{ form.title|render_label('Give me a title') }}
95+
96+
.. note::
97+
Symfony2 automatically internationalizes all labels and error messages.
98+
99+
The ``render_errors`` filter renders the field errors:
100+
101+
.. code-block:: jinja
102+
103+
{{ form.title|render_errors }}
104+
105+
.. tip::
106+
The ``render_errors`` can be used on a form or on a field.
107+
108+
You can also get the data associated with the field (the default data or the
109+
data submitted by the user), via the ``render_data`` filter:
110+
111+
.. code-block:: jinja
112+
113+
{{ form.title|render_data }}
114+
115+
{{ form.created_at|render_data|date('Y-m-d') }}
116+
117+
Defining the HTML Representation
118+
--------------------------------
119+
120+
All filters rely on Twig template blocks to render HTML. By default, Symfony2
121+
comes bundled with two templates that define all the needed blocks; one for
122+
form instances (``form.twig``), and one for field instances
123+
(``widgets.twig``).
124+
125+
Each filter is associated with one template block. For instance, the
126+
``render_errors`` filter looks for an ``errors`` block. The built-in one reads
127+
as follows:
128+
129+
.. code-block:: jinja
130+
131+
{# TwigBundle::form.twig #}
132+
133+
{% block errors %}
134+
{% if errors %}
135+
<ul>
136+
{% for error in errors %}
137+
<li>{% trans error.0 with error.1 from validators %}</li>
138+
{% endfor %}
139+
</ul>
140+
{% endif %}
141+
{% endblock errors %}
142+
143+
Here is the full list of filters and their associated block names:
144+
145+
================= ==================
146+
Filter Block Name
147+
================= ==================
148+
``render_errors`` ``errors``
149+
``render_hidden`` ``hidden``
150+
``render_label`` ``label``
151+
``render`` ``group`` or ``field`` (see below)
152+
================= ==================
153+
154+
The ``render_widget`` filter is a bit different as it selects the block to
155+
render based on the underscore version of the field class name. For instance,
156+
it looks for an ``input_field`` block when rendering an ``InputField``
157+
instance:
158+
159+
.. code-block:: jinja
160+
161+
{# TwigBundle::widgets.twig #}
162+
163+
{% block input_field %}
164+
{% tag "input" with attributes %}
165+
{% endblock input_field %}
166+
167+
If the block does not exist, the filter looks for a block for one of the field
168+
parent classes. That's why there is no default ``password_field`` block as its
169+
representation is exactly the same as its parent class (``input_field``).
170+
171+
Customizing Field Representation
172+
--------------------------------
173+
174+
The easiest way to customize a widget is by passing custom HTML attributes as
175+
an argument to ``render_widget``:
176+
177+
.. code-block:: jinja
178+
179+
{{ form.title|render_widget(['class': 'important']) }}
180+
181+
If you want to completely override the HTML representation of a widget, pass a
182+
Twig template that defines the needed template block:
183+
184+
.. code-block:: jinja
185+
186+
{{ form.title|render_widget([], 'HelloBundle::widgets.twig') }}
187+
188+
The ``HelloBundle::widgets.twig`` is a regular Twig template containing blocks
189+
defining the HTML representation for widgets you want to override:
190+
191+
.. code-block:: jinja
192+
193+
{# HelloBundle/Resources/views/widgets.twig #}
194+
195+
{% block input_field %}
196+
<div class="input_field">
197+
{% tag "input" with attributes %}
198+
</div>
199+
{% endblock input_field %}
200+
201+
In this example, the ``input_field`` block is redefined. Instead of changing
202+
the default representation, you can also extend the default one by using the
203+
Twig native inheritance feature:
204+
205+
.. code-block:: jinja
206+
207+
{# HelloBundle/Resources/views/widgets.twig #}
208+
209+
{% extends 'TwigBundle::widgets.twig' %}
210+
211+
{% block date_time_field %}
212+
<div class="important_date_field">
213+
{% parent %}
214+
</div>
215+
{% endblock date_time_field %}
216+
217+
If you want to customize all fields of a given form, use the ``form_theme``
218+
tag:
219+
220+
.. code-block:: jinja
221+
222+
{% form_theme form 'HelloBundle::widgets.twig' %}
223+
224+
Whenever you call the ``render_widget`` filter on the ``form`` after this
225+
call, Symfony2 will look for a representation in your template before falling
226+
back to the default one.
227+
228+
If the widget blocks are defined in several templates, add them as an ordered
229+
array:
230+
231+
.. code-block:: jinja
232+
233+
{% form_theme form ['HelloBundle::form.twig', 'HelloBundle::widgets.twig', 'HelloBundle::hello_widgets.twig'] %}
234+
235+
A theme can be attached to a whole form (as above) or just for a field group:
236+
237+
.. code-block:: jinja
238+
239+
{% form_theme form.user 'HelloBundle::widgets.twig' %}
240+
241+
Finally, customizing the representation of all forms of an application is
242+
possible via configuration:
243+
244+
.. configuration-block::
245+
246+
.. code-block:: yaml
247+
248+
# app/config/config.yml
249+
twig.config:
250+
form:
251+
resources: [BlogBundle::widgets.twig]
252+
253+
.. code-block:: xml
254+
255+
<!-- app/config/config.xml -->
256+
<twig:config>
257+
<twig:form>
258+
<twig:resource>BlogBundle::widgets.twig</twig:resource>
259+
</twig:form>
260+
</twig:config>
261+
262+
.. code-block:: php
263+
264+
// app/config/config.php
265+
$container->loadFromExtension('twig', 'config', array('form' => array(
266+
'resources' => array('BlogBundle::widgets.twig'),
267+
)));
268+
269+
... configuration XML/YAML/PHP
270+
271+
Prototyping
272+
-----------
273+
274+
When prototyping a form, you can use the ``render`` filter instead of manually
275+
rendering all fields:
276+
277+
.. code-block:: jinja
278+
279+
<form action="#" {{ form|render_enctype }} method="post">
280+
{{ form|render }}
281+
<input type="submit" />
282+
</form>
283+
284+
The ``render`` filter can also be used to render a field "row":
285+
286+
.. code-block:: jinja
287+
288+
<form action="#" {{ form|render_enctype }} method="post">
289+
{{ form|render_errors }}
290+
<table>
291+
{{ form.first_name|render }}
292+
{{ form.last_name|render }}
293+
</table>
294+
{{ form|render_hidden }}
295+
<input type="submit" />
296+
</form>
297+
298+
The ``render`` filter uses the ``group`` and ``field`` blocks for rendering:
299+
300+
.. code-block:: jinja
301+
302+
{# TwigBundle::form.twig #}
303+
304+
{% block group %}
305+
{{ group|render_errors }}
306+
<table>
307+
{% for field in group %}
308+
{% if not field.ishidden %}
309+
{{ field|render }}
310+
{% endif %}
311+
{% endfor %}
312+
</table>
313+
{{ group|render_hidden }}
314+
{% endblock group %}
315+
316+
{% block field %}
317+
<tr>
318+
<th>{{ field|render_label }}</th>
319+
<td>
320+
{{ field|render_errors }}
321+
{{ field|render_widget }}
322+
</td>
323+
</tr>
324+
{% endblock field %}
325+
326+
As for any other filter, ``render`` accepts a template as an argument to
327+
override the default representation:
328+
329+
.. code-block:: jinja
330+
331+
{{ form|render("HelloBundle::form.twig") }}
332+
333+
.. caution::
334+
The ``render`` filter is not very flexible and should only be used to
335+
build prototypes.
336+
337+
.. _branch: http://github.com/fabpot/symfony/tree/fields_as_templates

0 commit comments

Comments
 (0)