From 98de95a1a7c4c35b293e5dab001d0a361ea8ba96 Mon Sep 17 00:00:00 2001 From: Charles Sarrazin Date: Fri, 21 Mar 2014 17:21:01 +0100 Subject: [PATCH] [Form] Added documentation for Form Events Added initial documentation for Form Events: * List of events * Use cases for each event * Description of the events workflow * Flow charts for illustration Updated PR with comments from @WouterJ and @MyKiwi Took into account @cordoval's feedback Additional improvements * Added more examples from the Form component's code * Moved the cookbook's 'register a subscriber using a callable' section into the form events documentation Took into account @xabbuh's feedback Fixed missing new line Removed superfluous comma. Updated from feedback Moved the list of events down in the listener and subscriber section * Formatted the list as a table, exposing the constant values; * Added references to the form event information table; * Added caution sections for actions that should prevented while in each event. Added the form_events link in the components map file, a.k.a. 'Added the missing link' Added missing newlines Added cross-reference in the form events cookbook Updated based on Luis' feedback Added tables describing the form and event values: * Model data * Normalized data * View data * Event data Small fixes Updated a few wordings to make them more clear Changed important directive to caution Removed sidebar section about form extensions. Renamed ``{EVENT}`` to ``FormEvents::{EVENT}``, and added code snippet Last small changes Fixed underline too short --- components/form/form_events.rst | 398 ++++++++++++++++++++ components/form/index.rst | 1 + components/map.rst.inc | 1 + cookbook/form/dynamic_form_modification.rst | 23 +- images/components/form/general_flow.png | Bin 0 -> 10427 bytes images/components/form/set_data_flow.png | Bin 0 -> 8588 bytes images/components/form/submission_flow.png | Bin 0 -> 10285 bytes 7 files changed, 404 insertions(+), 19 deletions(-) create mode 100644 components/form/form_events.rst create mode 100644 images/components/form/general_flow.png create mode 100644 images/components/form/set_data_flow.png create mode 100644 images/components/form/submission_flow.png diff --git a/components/form/form_events.rst b/components/form/form_events.rst new file mode 100644 index 00000000000..1b81360f529 --- /dev/null +++ b/components/form/form_events.rst @@ -0,0 +1,398 @@ +.. index:: + single: Forms; Form Events + +Form Events +=========== + +The Form component provides a structured process to let you customize your +forms, by making use of the :doc:`EventDispatcher ` +component. Using form events, you may modify information or fields at +different steps of the workflow: from the population of the form to the +submission of the data from the request. + +Registering an event listener is very easy using the Form component. + +For example, if you wish to register a function to the +``FormEvents::PRE_SUBMIT`` event, the following code lets you add a field, +depending on the request' values:: + + // ... + + use Symfony\Component\Form\FormEvent; + use Symfony\Component\Form\FormEvents; + + $listener = function (FormEvent $event) { + // ... + }; + + $form = $formFactory->createBuilder() + // add form fields + ->addEventListener(FormEvents::PRE_SUBMIT, $listener); + + // ... + +The Form Workflow +----------------- + +The Form Submission Workflow +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. image:: /images/components/form/general_flow.png + :align: center + +1) Pre-populating the Form (``FormEvents::PRE_SET_DATA`` and ``FormEvents::POST_SET_DATA``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. image:: /images/components/form/set_data_flow.png + :align: center + +Two events are dispatched during pre-population of a form, when +:method:`Form::setData() ` +is called: ``FormEvents::PRE_SET_DATA`` and ``FormEvents::POST_SET_DATA``. + +A) The ``FormEvents::PRE_SET_DATA`` Event +......................................... + +The ``FormEvents::PRE_SET_DATA`` event is dispatched at the beginning of the +``Form::setData()`` method. It can be used to: + +* Modify the data given during pre-population; +* Modify a form depending on the pre-populated data (adding or removing fields dynamically). + +:ref:`Form Events Information Table` + ++-----------------+-----------+ +| **Data type** | **Value** | ++-----------------+-----------+ +| Model data | ``null`` | ++-----------------+-----------+ +| Normalized data | ``null`` | ++-----------------+-----------+ +| View data | ``null`` | ++-----------------+-----------+ + +.. caution:: + + During ``FormEvents::PRE_SET_DATA``, + :method:`Form::setData() ` + is locked and will throw an exception if used. If you wish to modify + data, you should use + :method:`FormEvent::setData() ` + instead. + +.. sidebar:: ``FormEvents::PRE_SET_DATA`` in the Form component + + The ``collection`` form type relies on the + :class:`Symfony\\Component\\Form\\Extension\\Core\\EventListener\\ResizeFormListener` + subscriber, listening to the ``FormEvents::PRE_SET_DATA`` event in order + to reorder the form's fields depending on the data from the pre-populated + object, by removing and adding all form rows. + +B) The ``FormEvents::POST_SET_DATA`` Event +.......................................... + +The ``FormEvents::POST_SET_DATA`` event is dispatched at the end of the +:method:`Form::setData() ` +method. This event is mostly here for reading data after having pre-populated +the form. + +:ref:`Form Events Information Table` + ++-----------------+------------------------------------------------------+ +| **Data type** | **Value** | ++-----------------+------------------------------------------------------+ +| Model data | Model data injected into ``setData()`` | ++-----------------+------------------------------------------------------+ +| Normalized data | Model data transformed using a model transformer | ++-----------------+------------------------------------------------------+ +| View data | Normalized data transformed using a view transformer | ++-----------------+------------------------------------------------------+ + +.. sidebar:: ``FormEvents::POST_SET_DATA`` in the Form component + + The :class:`Symfony\\Component\\Form\\Extension\\DataCollector\\EventListener\\DataCollectorListener` + class is subscribed to listen to the ``FormEvents::POST_SET_DATA`` event + in order to collect information about the forms from the denormalized + model and view data. + +2) Submitting a Form (``FormEvents::PRE_SUBMIT``, ``FormEvents::SUBMIT`` and ``FormEvents::POST_SUBMIT``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. image:: /images/components/form/submission_flow.png + :align: center + +Three events are dispatched when +:method:`Form::handleRequest() ` +or :method:`Form::submit() ` are +called: ``FormEvents::PRE_SUBMIT``, ``FormEvents::SUBMIT``, +``FormEvents::POST_SUBMIT``. + +A) The ``FormEvents::PRE_SUBMIT`` Event +....................................... + +The ``FormEvents::PRE_SUBMIT`` event is dispatched at the beginning of the +:method:`Form::submit() ` method. + +It can be used to: + +* Change data from the request, before submitting the data to the form. +* Add or remove form fields, before submitting the data to the form. + +:ref:`Form Events Information Table` + ++-----------------+------------------------------------------+ +| **Data type** | **Value** | ++-----------------+------------------------------------------+ +| Model data | Same as in ``FormEvents::POST_SET_DATA`` | ++-----------------+------------------------------------------+ +| Normalized data | Same as in ``FormEvents::POST_SET_DATA`` | ++-----------------+------------------------------------------+ +| View data | Same as in ``FormEvents::POST_SET_DATA`` | ++-----------------+------------------------------------------+ + +.. sidebar:: ``FormEvents::PRE_SUBMIT`` in the Form component + + The :class:`Symfony\\Component\\Form\\Extension\\Core\\EventListener\\TrimListener` + subscriber subscribes to the ``FormEvents::PRE_SUBMIT`` event in order to + trim the request's data (for string values). + The :class:`Symfony\\Component\\Form\\Extension\\Csrf\\EventListener\\CsrfValidationListener` + subscriber subscribes to the ``FormEvents::PRE_SUBMIT`` event in order to + validate the CSRF token. + +B) The ``FormEvents::SUBMIT`` Event +................................... + +The ``FormEvents::SUBMIT`` event is dispatched just before the +:method:`Form::submit() ` method +transforms back the normalized data to the model and view data. + +It can be used to change data from the normalized representation of the data. + +:ref:`Form Events Information Table` + ++-----------------+-------------------------------------------------------------------------------------+ +| **Data type** | **Value** | ++-----------------+-------------------------------------------------------------------------------------+ +| Model data | Same as in ``FormEvents::POST_SET_DATA`` | ++-----------------+-------------------------------------------------------------------------------------+ +| Normalized data | Data from the request reverse-transformed from the request using a view transformer | ++-----------------+-------------------------------------------------------------------------------------+ +| View data | Same as in ``FormEvents::POST_SET_DATA`` | ++-----------------+-------------------------------------------------------------------------------------+ + +.. caution:: + + At this point, you cannot add or remove fields to the form. + +.. sidebar:: ``FormEvents::SUBMIT`` in the Form component + + The :class:`Symfony\\Component\\Form\\Extension\\Core\\EventListener\\ResizeFormListener` + subscribes to the ``FormEvents::SUBMIT`` event in order to remove the + fields that need to be removed whenever manipulating a collection of forms + for which ``allow_delete`` has been enabled. + +C) The ``FormEvents::POST_SUBMIT`` Event +........................................ + +The ``FormEvents::POST_SUBMIT`` event is dispatched after the +:method:`Form::submit() ` once the +model and view data have been denormalized. + +It can be used to fetch data after denormalization. + +:ref:`Form Events Information Table` + ++-----------------+---------------------------------------------------------------+ +| **Data type** | **Value** | ++-----------------+---------------------------------------------------------------+ +| Model data | Normalized data reverse-transformed using a model transformer | ++-----------------+---------------------------------------------------------------+ +| Normalized data | Same as in ``FormEvents::POST_SUBMIT`` | ++-----------------+---------------------------------------------------------------+ +| View data | Normalized data transformed using a view transformer | ++-----------------+---------------------------------------------------------------+ + +.. caution:: + + At this point, you cannot add or remove fields to the form. + +.. sidebar:: ``FormEvents::POST_SUBMIT`` in the Form component + + The :class:`Symfony\\Component\\Form\\Extension\\DataCollector\\EventListener\\DataCollectorListener` + subscribes to the ``FormEvents::POST_SUBMIT`` event in order to collect + information about the forms. + The :class:`Symfony\\Component\\Form\\Extension\\Validator\\EventListener\\ValidationListener` + subscribes to the ``FormEvents::POST_SUBMIT`` event in order to + automatically validate the denormalized object, and update the normalized + as well as the view's representations. + +Registering Event Listeners or Event Subscribers +------------------------------------------------ + +In order to be able to use Form events, you need to create an event listener +or an event subscriber, and register it to an event. + +The name of each of the "form" events is defined as a constant on the +:class:`Symfony\\Component\\Form\\FormEvents` class. +Additionally, each event callback (listener or subscriber method) is passed a +single argument, which is an instance of +:class:`Symfony\\Component\\Form\\FormEvent`. The event object contains a +reference to the current state of the form, and the current data being +processed. + +.. _component-form-event-table: + ++--------------------+-------------------------------+------------------+ +| **Name** | ``FormEvents`` **Constant** | **Event's data** | ++--------------------+-------------------------------+------------------+ +| form.pre_set_data | ``FormEvents::PRE_SET_DATA`` | Model data | ++--------------------+-------------------------------+------------------+ +| form.post_set_data | ``FormEvents::POST_SET_DATA`` | Model data | ++--------------------+-------------------------------+------------------+ +| form.pre_bind | ``FormEvents::PRE_SUBMIT`` | Request data | ++--------------------+-------------------------------+------------------+ +| form.bind | ``FormEvents::SUBMIT`` | Normalized data | ++--------------------+-------------------------------+------------------+ +| form.post_bind | ``FormEvents::POST_SUBMIT`` | View data | ++--------------------+-------------------------------+------------------+ + +.. versionadded:: 2.3 + + Before Symfony 2.3, ``FormEvents::PRE_SUBMIT``, ``FormEvents::SUBMIT`` + and ``FormEvents::POST_SUBMIT`` were called ``FormEvents::PRE_BIND``, + ``FormEvents::BIND`` and ``FormEvents::POST_BIND``. + +.. caution:: + + The ``FormEvents::PRE_BIND``, ``FormEvents::BIND`` and + ``FormEvents::POST_BIND`` constants will be removed in version 3.0 of + Symfony. + The event names still keep their original values, so make sure you use the + ``FormEvents`` constants in your code for forward compatibility. + +Event Listeners +~~~~~~~~~~~~~~~ + +An event listener may be any type of valid callable. + +Creating and binding an event listener to the form is very easy:: + + // ... + + use Symfony\Component\Form\FormEvent; + use Symfony\Component\Form\FormEvents; + + $form = $formFactory->createBuilder() + ->add('username', 'text') + ->add('show_email', 'checkbox') + ->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { + $user = $event->getData(); + $form = $event->getForm(); + + if (!$user) { + return; + } + + // Check whether the user has chosen to display his email or not. + // If the data was submitted previously, the additional value that is + // included in the request variables needs to be removed. + if (true === $user['show_email']) { + $form->add('email', 'email'); + } else { + unset($user['email']); + $event->setData($user); + } + }) + ->getForm(); + + // ... + +When you have created a form type class, you can use one of its methods as a +callback for better readability:: + + // ... + + class SubscriptionType extends AbstractType + { + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->add('username', 'text'); + $builder->add('show_email', 'checkbox'); + $builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData')); + } + + public function onPreSetData(FormEvent $event) + { + // ... + } + } + +Event Subscribers +~~~~~~~~~~~~~~~~~ + +Event subscribers have different uses: + +* Improving readability; +* Listening to multiple events; +* Regrouping multiple listeners inside a single class. + +.. code-block:: php + + use Symfony\Component\EventDispatcher\EventSubscriberInterface; + use Symfony\Component\Form\FormEvent; + use Symfony\Component\Form\FormEvents; + + class AddEmailFieldListener implements EventSubscriberInterface + { + public function getSubscribedEvents() + { + return array( + FormEvents::PRE_SET_DATA => 'onPreSetData', + FormEvents::PRE_SUBMIT => 'onPreSubmit', + ); + } + + public function onPreSetData(FormEvent $event) + { + $user = $event->getData(); + $form = $event->getForm(); + + // Check whether the user from the initial data has chosen to + // display his email or not. + if (true === $user->isShowEmail()) { + $form->add('email', 'email'); + } + } + + public function onPreSubmit(FormEvent $event) + { + $user = $event->getData(); + $form = $event->getForm(); + + if (!$user) { + return; + } + + // Check whether the user has chosen to display his email or not. + // If the data was submitted previously, the additional value that + // is included in the request variables needs to be removed. + if (true === $user['show_email']) { + $form->add('email', 'email'); + } else { + unset($user['email']); + $event->setData($user); + } + } + } + +To register the event subscriber, use the addEventSubscriber() method:: + + // ... + + $form = $formFactory->createBuilder() + ->add('username', 'text') + ->add('show_email', 'checkbox') + ->addEventSubscriber(new AddEmailFieldListener()) + ->getForm(); + + // ... diff --git a/components/form/index.rst b/components/form/index.rst index 5ea5add00f6..a2de93c6245 100644 --- a/components/form/index.rst +++ b/components/form/index.rst @@ -6,3 +6,4 @@ introduction type_guesser + form_events diff --git a/components/map.rst.inc b/components/map.rst.inc index fbc1872afb8..88909e4301e 100644 --- a/components/map.rst.inc +++ b/components/map.rst.inc @@ -68,6 +68,7 @@ * :doc:`/components/form/index` * :doc:`/components/form/introduction` + * :doc:`/components/form/form_events` * :doc:`/components/form/type_guesser` * :doc:`/components/http_foundation/index` diff --git a/cookbook/form/dynamic_form_modification.rst b/cookbook/form/dynamic_form_modification.rst index 2add7ddd759..e7109617793 100644 --- a/cookbook/form/dynamic_form_modification.rst +++ b/cookbook/form/dynamic_form_modification.rst @@ -24,6 +24,10 @@ Example: on a registration form, you have a "country" field and a "state" field which should populate dynamically based on the value in the "country" field. +If you wish to learn more about the basics behind form events, you can +take a look at the :doc:`Form Events ` +documentation. + .. _cookbook-form-events-underlying-data: Customizing your Form based on the underlying Data @@ -134,25 +138,6 @@ the event listener might look like the following:: :method:`FormInterface::add ` was added in Symfony 2.2. -.. note:: - You can of course use any callback type instead of a closure, e.g. a method - call on the ``ProductType`` object itself for better readability:: - - // ... - class ProductType extends AbstractType - { - public function buildForm(FormBuilderInterface $builder, array $options) - { - // ... - $builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData')); - } - - public function onPreSetData(FormEvent $event) - { - // ... - } - } - .. note:: The ``FormEvents::PRE_SET_DATA`` line actually resolves to the string diff --git a/images/components/form/general_flow.png b/images/components/form/general_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..31650e52af6f87244424b62856ebdcb5078c7454 GIT binary patch literal 10427 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 U8J=Zj{G$*9sp+WJs#w1J4|C!=>Hq)$ literal 0 HcmV?d00001 diff --git a/images/components/form/set_data_flow.png b/images/components/form/set_data_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..3cd4b1e2f7bf878d3ec455eda8eb9069584ff252 GIT binary patch literal 8588 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

<6Kw!{xy)=)~3Acn+iP= zTibg(GT0s=1y6PtQIMQ1M+r7pX&@Z`CtcqoHRF<_%}+pUP7bR4U+8+o7SfS-NBX|G zgM01gVVbO%jVRY*6!!i_6Xl8phciXO=L*%;vCs0f^YQpM7CRX*4(&HN3oa#}Ww)N! zl70q(D1KesT`chyF2^(bo?I4GRZmpI_og7%{EnN!+5MFL=Vz+rE4_^P4p;A#z9hVD znrPU@wo9ud!2Jlj6Cpvy71lH1`Nj*VP)qZcnil?1lsce?FZj}az-{YymoTLCbDBEtM6p+ zX$_fFK(=Ew)VqeNw94G_GjAGFhwW?a?rZ%7rB@YHS1Y-w6k1l4zKjs7qI*}goSS?V zIFQoG=G)fcuAh({0}I1aU{FZ0iivklm;<+z^d0}#@$)`A*RB~G1}+$y{rS$GbjO!+ zG{QPk;4cM>z|ilk3wQAa^K~6fDRe-8Z|F&T_nyk78#ZSzYq=@lVw_{0BwJ@$XpYNf5O!(tefiZz}z-}|Rjt*NG`TB~CH?mqy=(0juG literal 0 HcmV?d00001 diff --git a/images/components/form/submission_flow.png b/images/components/form/submission_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..a3c6e9cfb90ce85d38337a1a4b32b15fc8f5d49c GIT binary patch literal 10285 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 literal 0 HcmV?d00001 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy