Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf665e14

Browse files
committed
featuresymfony#3704 [Form] Added documentation for Form Events (csarrazi)
This PR was merged into the 2.3 branch.Discussion----------[Form] Added documentation for Form Events| Q | A| ------------- | ---| Doc fix? | no| New docs? | yes| Applies to | >=2.3| Fixed tickets | DunnoAdded initial documentation for Form Events:* List of events* Use cases for each event* Description of the events workflow* Flow charts for illustration* Registering event listeners or subscribers in a form* Describing the data available for each eventCommits-------98de95a [Form] Added documentation for Form Events
2 parents127beed +98de95a commitf665e14

File tree

7 files changed

+404
-19
lines changed

7 files changed

+404
-19
lines changed

‎components/form/form_events.rst

Lines changed: 398 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,398 @@
1+
..index::
2+
single: Forms; Form Events
3+
4+
Form Events
5+
===========
6+
7+
The Form component provides a structured process to let you customize your
8+
forms, by making use of the:doc:`EventDispatcher</components/event_dispatcher/introduction>`
9+
component. Using form events, you may modify information or fields at
10+
different steps of the workflow: from the population of the form to the
11+
submission of the data from the request.
12+
13+
Registering an event listener is very easy using the Form component.
14+
15+
For example, if you wish to register a function to the
16+
``FormEvents::PRE_SUBMIT`` event, the following code lets you add a field,
17+
depending on the request' values::
18+
19+
// ...
20+
21+
use Symfony\Component\Form\FormEvent;
22+
use Symfony\Component\Form\FormEvents;
23+
24+
$listener = function (FormEvent $event) {
25+
// ...
26+
};
27+
28+
$form = $formFactory->createBuilder()
29+
// add form fields
30+
->addEventListener(FormEvents::PRE_SUBMIT, $listener);
31+
32+
// ...
33+
34+
The Form Workflow
35+
-----------------
36+
37+
The Form Submission Workflow
38+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39+
40+
..image::/images/components/form/general_flow.png
41+
:align:center
42+
43+
1) Pre-populating the Form (``FormEvents::PRE_SET_DATA`` and ``FormEvents::POST_SET_DATA``)
44+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45+
46+
..image::/images/components/form/set_data_flow.png
47+
:align:center
48+
49+
Two events are dispatched during pre-population of a form, when
50+
:method:`Form::setData() <Symfony\\Component\\Form\\Form::setData>`
51+
is called: ``FormEvents::PRE_SET_DATA`` and ``FormEvents::POST_SET_DATA``.
52+
53+
A) The ``FormEvents::PRE_SET_DATA`` Event
54+
.........................................
55+
56+
The ``FormEvents::PRE_SET_DATA`` event is dispatched at the beginning of the
57+
``Form::setData()`` method. It can be used to:
58+
59+
* Modify the data given during pre-population;
60+
* Modify a form depending on the pre-populated data (adding or removing fields dynamically).
61+
62+
:ref:`Form Events Information Table<component-form-event-table>`
63+
64+
+-----------------+-----------+
65+
| **Data type**| **Value**|
66+
+-----------------+-----------+
67+
| Model data| ``null``|
68+
+-----------------+-----------+
69+
| Normalized data| ``null``|
70+
+-----------------+-----------+
71+
| View data| ``null``|
72+
+-----------------+-----------+
73+
74+
..caution::
75+
76+
During ``FormEvents::PRE_SET_DATA``,
77+
:method:`Form::setData() <Symfony\\Component\\Form\\Form::setData>`
78+
is locked and will throw an exception if used. If you wish to modify
79+
data, you should use
80+
:method:`FormEvent::setData() <Symfony\\Component\\Form\\FormEvent::setData>`
81+
instead.
82+
83+
..sidebar::``FormEvents::PRE_SET_DATA`` in the Form component
84+
85+
The ``collection`` form type relies on the
86+
:class:`Symfony\\Component\\Form\\Extension\\Core\\EventListener\\ResizeFormListener`
87+
subscriber, listening to the ``FormEvents::PRE_SET_DATA`` event in order
88+
to reorder the form's fields depending on the data from the pre-populated
89+
object, by removing and adding all form rows.
90+
91+
B) The ``FormEvents::POST_SET_DATA`` Event
92+
..........................................
93+
94+
The ``FormEvents::POST_SET_DATA`` event is dispatched at the end of the
95+
:method:`Form::setData() <Symfony\\Component\\Form\\Form::setData>`
96+
method. This event is mostly here for reading data after having pre-populated
97+
the form.
98+
99+
:ref:`Form Events Information Table<component-form-event-table>`
100+
101+
+-----------------+------------------------------------------------------+
102+
| **Data type**| **Value**|
103+
+-----------------+------------------------------------------------------+
104+
| Model data| Model data injected into ``setData()``|
105+
+-----------------+------------------------------------------------------+
106+
| Normalized data| Model data transformed using a model transformer|
107+
+-----------------+------------------------------------------------------+
108+
| View data| Normalized data transformed using a view transformer|
109+
+-----------------+------------------------------------------------------+
110+
111+
..sidebar::``FormEvents::POST_SET_DATA`` in the Form component
112+
113+
The:class:`Symfony\\Component\\Form\\Extension\\DataCollector\\EventListener\\DataCollectorListener`
114+
class is subscribed to listen to the ``FormEvents::POST_SET_DATA`` event
115+
in order to collect information about the forms from the denormalized
116+
model and view data.
117+
118+
2) Submitting a Form (``FormEvents::PRE_SUBMIT``, ``FormEvents::SUBMIT`` and ``FormEvents::POST_SUBMIT``)
119+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120+
121+
..image::/images/components/form/submission_flow.png
122+
:align:center
123+
124+
Three events are dispatched when
125+
:method:`Form::handleRequest() <Symfony\\Component\\Form\\Form::handleRequest>`
126+
or:method:`Form::submit() <Symfony\\Component\\Form\\Form::submit>` are
127+
called: ``FormEvents::PRE_SUBMIT``, ``FormEvents::SUBMIT``,
128+
``FormEvents::POST_SUBMIT``.
129+
130+
A) The ``FormEvents::PRE_SUBMIT`` Event
131+
.......................................
132+
133+
The ``FormEvents::PRE_SUBMIT`` event is dispatched at the beginning of the
134+
:method:`Form::submit() <Symfony\\Component\\Form\\Form::submit>` method.
135+
136+
It can be used to:
137+
138+
* Change data from the request, before submitting the data to the form.
139+
* Add or remove form fields, before submitting the data to the form.
140+
141+
:ref:`Form Events Information Table<component-form-event-table>`
142+
143+
+-----------------+------------------------------------------+
144+
| **Data type**| **Value**|
145+
+-----------------+------------------------------------------+
146+
| Model data| Same as in ``FormEvents::POST_SET_DATA``|
147+
+-----------------+------------------------------------------+
148+
| Normalized data| Same as in ``FormEvents::POST_SET_DATA``|
149+
+-----------------+------------------------------------------+
150+
| View data| Same as in ``FormEvents::POST_SET_DATA``|
151+
+-----------------+------------------------------------------+
152+
153+
..sidebar::``FormEvents::PRE_SUBMIT`` in the Form component
154+
155+
The:class:`Symfony\\Component\\Form\\Extension\\Core\\EventListener\\TrimListener`
156+
subscriber subscribes to the ``FormEvents::PRE_SUBMIT`` event in order to
157+
trim the request's data (for string values).
158+
The:class:`Symfony\\Component\\Form\\Extension\\Csrf\\EventListener\\CsrfValidationListener`
159+
subscriber subscribes to the ``FormEvents::PRE_SUBMIT`` event in order to
160+
validate the CSRF token.
161+
162+
B) The ``FormEvents::SUBMIT`` Event
163+
...................................
164+
165+
The ``FormEvents::SUBMIT`` event is dispatched just before the
166+
:method:`Form::submit() <Symfony\\Component\\Form\\Form::submit>` method
167+
transforms back the normalized data to the model and view data.
168+
169+
It can be used to change data from the normalized representation of the data.
170+
171+
:ref:`Form Events Information Table<component-form-event-table>`
172+
173+
+-----------------+-------------------------------------------------------------------------------------+
174+
| **Data type**| **Value**|
175+
+-----------------+-------------------------------------------------------------------------------------+
176+
| Model data| Same as in ``FormEvents::POST_SET_DATA``|
177+
+-----------------+-------------------------------------------------------------------------------------+
178+
| Normalized data| Data from the request reverse-transformed from the request using a view transformer|
179+
+-----------------+-------------------------------------------------------------------------------------+
180+
| View data| Same as in ``FormEvents::POST_SET_DATA``|
181+
+-----------------+-------------------------------------------------------------------------------------+
182+
183+
..caution::
184+
185+
At this point, you cannot add or remove fields to the form.
186+
187+
..sidebar::``FormEvents::SUBMIT`` in the Form component
188+
189+
The:class:`Symfony\\Component\\Form\\Extension\\Core\\EventListener\\ResizeFormListener`
190+
subscribes to the ``FormEvents::SUBMIT`` event in order to remove the
191+
fields that need to be removed whenever manipulating a collection of forms
192+
for which ``allow_delete`` has been enabled.
193+
194+
C) The ``FormEvents::POST_SUBMIT`` Event
195+
........................................
196+
197+
The ``FormEvents::POST_SUBMIT`` event is dispatched after the
198+
:method:`Form::submit() <Symfony\\Component\\Form\\Form::submit>` once the
199+
model and view data have been denormalized.
200+
201+
It can be used to fetch data after denormalization.
202+
203+
:ref:`Form Events Information Table<component-form-event-table>`
204+
205+
+-----------------+---------------------------------------------------------------+
206+
| **Data type**| **Value**|
207+
+-----------------+---------------------------------------------------------------+
208+
| Model data| Normalized data reverse-transformed using a model transformer|
209+
+-----------------+---------------------------------------------------------------+
210+
| Normalized data| Same as in ``FormEvents::POST_SUBMIT``|
211+
+-----------------+---------------------------------------------------------------+
212+
| View data| Normalized data transformed using a view transformer|
213+
+-----------------+---------------------------------------------------------------+
214+
215+
..caution::
216+
217+
At this point, you cannot add or remove fields to the form.
218+
219+
..sidebar::``FormEvents::POST_SUBMIT`` in the Form component
220+
221+
The:class:`Symfony\\Component\\Form\\Extension\\DataCollector\\EventListener\\DataCollectorListener`
222+
subscribes to the ``FormEvents::POST_SUBMIT`` event in order to collect
223+
information about the forms.
224+
The:class:`Symfony\\Component\\Form\\Extension\\Validator\\EventListener\\ValidationListener`
225+
subscribes to the ``FormEvents::POST_SUBMIT`` event in order to
226+
automatically validate the denormalized object, and update the normalized
227+
as well as the view's representations.
228+
229+
Registering Event Listeners or Event Subscribers
230+
------------------------------------------------
231+
232+
In order to be able to use Form events, you need to create an event listener
233+
or an event subscriber, and register it to an event.
234+
235+
The name of each of the "form" events is defined as a constant on the
236+
:class:`Symfony\\Component\\Form\\FormEvents` class.
237+
Additionally, each event callback (listener or subscriber method) is passed a
238+
single argument, which is an instance of
239+
:class:`Symfony\\Component\\Form\\FormEvent`. The event object contains a
240+
reference to the current state of the form, and the current data being
241+
processed.
242+
243+
.. _component-form-event-table:
244+
245+
+--------------------+-------------------------------+------------------+
246+
| **Name**| ``FormEvents`` **Constant**| **Event's data**|
247+
+--------------------+-------------------------------+------------------+
248+
| form.pre_set_data| ``FormEvents::PRE_SET_DATA``| Model data|
249+
+--------------------+-------------------------------+------------------+
250+
| form.post_set_data| ``FormEvents::POST_SET_DATA``| Model data|
251+
+--------------------+-------------------------------+------------------+
252+
| form.pre_bind| ``FormEvents::PRE_SUBMIT``| Request data|
253+
+--------------------+-------------------------------+------------------+
254+
| form.bind| ``FormEvents::SUBMIT``| Normalized data|
255+
+--------------------+-------------------------------+------------------+
256+
| form.post_bind| ``FormEvents::POST_SUBMIT``| View data|
257+
+--------------------+-------------------------------+------------------+
258+
259+
..versionadded::2.3
260+
261+
Before Symfony 2.3, ``FormEvents::PRE_SUBMIT``, ``FormEvents::SUBMIT``
262+
and ``FormEvents::POST_SUBMIT`` were called ``FormEvents::PRE_BIND``,
263+
``FormEvents::BIND`` and ``FormEvents::POST_BIND``.
264+
265+
..caution::
266+
267+
The ``FormEvents::PRE_BIND``, ``FormEvents::BIND`` and
268+
``FormEvents::POST_BIND`` constants will be removed in version 3.0 of
269+
Symfony.
270+
The event names still keep their original values, so make sure you use the
271+
``FormEvents`` constants in your code for forward compatibility.
272+
273+
Event Listeners
274+
~~~~~~~~~~~~~~~
275+
276+
An event listener may be any type of valid callable.
277+
278+
Creating and binding an event listener to the form is very easy::
279+
280+
// ...
281+
282+
use Symfony\Component\Form\FormEvent;
283+
use Symfony\Component\Form\FormEvents;
284+
285+
$form = $formFactory->createBuilder()
286+
->add('username', 'text')
287+
->add('show_email', 'checkbox')
288+
->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
289+
$user = $event->getData();
290+
$form = $event->getForm();
291+
292+
if (!$user) {
293+
return;
294+
}
295+
296+
// Check whether the user has chosen to display his email or not.
297+
// If the data was submitted previously, the additional value that is
298+
// included in the request variables needs to be removed.
299+
if (true === $user['show_email']) {
300+
$form->add('email', 'email');
301+
} else {
302+
unset($user['email']);
303+
$event->setData($user);
304+
}
305+
})
306+
->getForm();
307+
308+
// ...
309+
310+
When you have created a form type class, you can use one of its methods as a
311+
callback for better readability::
312+
313+
// ...
314+
315+
class SubscriptionType extends AbstractType
316+
{
317+
public function buildForm(FormBuilderInterface $builder, array $options)
318+
{
319+
$builder->add('username', 'text');
320+
$builder->add('show_email', 'checkbox');
321+
$builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'));
322+
}
323+
324+
public function onPreSetData(FormEvent $event)
325+
{
326+
// ...
327+
}
328+
}
329+
330+
Event Subscribers
331+
~~~~~~~~~~~~~~~~~
332+
333+
Event subscribers have different uses:
334+
335+
* Improving readability;
336+
* Listening to multiple events;
337+
* Regrouping multiple listeners inside a single class.
338+
339+
..code-block::php
340+
341+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
342+
use Symfony\Component\Form\FormEvent;
343+
use Symfony\Component\Form\FormEvents;
344+
345+
class AddEmailFieldListener implements EventSubscriberInterface
346+
{
347+
public function getSubscribedEvents()
348+
{
349+
return array(
350+
FormEvents::PRE_SET_DATA => 'onPreSetData',
351+
FormEvents::PRE_SUBMIT => 'onPreSubmit',
352+
);
353+
}
354+
355+
public function onPreSetData(FormEvent $event)
356+
{
357+
$user = $event->getData();
358+
$form = $event->getForm();
359+
360+
// Check whether the user from the initial data has chosen to
361+
// display his email or not.
362+
if (true === $user->isShowEmail()) {
363+
$form->add('email', 'email');
364+
}
365+
}
366+
367+
public function onPreSubmit(FormEvent $event)
368+
{
369+
$user = $event->getData();
370+
$form = $event->getForm();
371+
372+
if (!$user) {
373+
return;
374+
}
375+
376+
// Check whether the user has chosen to display his email or not.
377+
// If the data was submitted previously, the additional value that
378+
// is included in the request variables needs to be removed.
379+
if (true === $user['show_email']) {
380+
$form->add('email', 'email');
381+
} else {
382+
unset($user['email']);
383+
$event->setData($user);
384+
}
385+
}
386+
}
387+
388+
To register the event subscriber, use the addEventSubscriber() method::
389+
390+
// ...
391+
392+
$form = $formFactory->createBuilder()
393+
->add('username', 'text')
394+
->add('show_email', 'checkbox')
395+
->addEventSubscriber(new AddEmailFieldListener())
396+
->getForm();
397+
398+
// ...

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp