From 47da6b7d9dd322d1d39f25995b6d9a0ff16973b7 Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Wed, 29 Aug 2012 00:22:35 +0200 Subject: [PATCH 01/10] First draft for field type extensions (#814) --- cookbook/form/create_field_type_extension.rst | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 cookbook/form/create_field_type_extension.rst diff --git a/cookbook/form/create_field_type_extension.rst b/cookbook/form/create_field_type_extension.rst new file mode 100644 index 00000000000..6faa3f9c55b --- /dev/null +++ b/cookbook/form/create_field_type_extension.rst @@ -0,0 +1,284 @@ +.. index:: + single: Form; Field type extension + +How to Create a Field Type Extension +====================================== + +:doc:`Custom form field types ` are great when you need field types with a specific purpose, +such as a gender selector, or a VAT number input. + +But sometimes, you don't really need to add new field types - you want to add features on top of existing field types. +This is where Field Type Extensions come in. + +Field Type Extensions have 2 main use cases : + +#. You want to add a **generic feature to several field types** (such as adding a "help" field to every field type) +#. You want to add a **specific feature to a single field type** (such as adding a "download" feature to the "file" field type) + +In both those cases, it might be possible to achieve your goal with custom form rendering, or custom form field types. But using +field type extensions can be cleaner (by limiting the amount of business logic in templates) and more flexible (you can add several type extensions +to a single form type). + +Field Type Extensions can achieve most of what custom field types can do, but instead of being field types of their own, +**they plug into existing field types**. + +Imagine that you manage a ``Media`` entity, and that each media is associated to a file. Your ``Media`` form uses a file type, but when editing the entity, +you would like to see its image automatically rendered next to the file input. + +You could of course do by fine-tuning your edition form template. But form type extensions allow you to do this in a nice DRY fashion. + +Defining the Field Type Extension +--------------------------------- + +Our first task will be to create the field type extension class. Let's call it ``ImageTypeExtension``. We will store the class in a file called +``ImageTypeExtension.php``, in the ``\Form\Type`` directory. + +When creating a form type extension, you can either implements the :class:`Symfony\\Component\\Form\\FormTypeExtensionInterface` +interface, or extends the :class:`Symfony\\Component\\Form\\AbstractTypeExtension` class. Most of the time, you will +end up extending the abstract class ; that's what we will do in this tutorial. + +.. code-block:: php + + // src/Acme/DemoBundle/Form/Type/ImageTypeExtension.php + namespace Acme\DemoBundle\Form\Type; + + use Symfony\Component\Form\AbstractTypeExtension; + use Symfony\Component\Form\FormTypeExtensionInterface; + + class ImageTypeExtension extends AbstractTypeExtension { + /** + * Returns the name of the type being extended. + * + * @return string The name of the type being extended + */ + public function getExtendedType() + { + return 'file'; + } + + } + +The only method you **must** implement is the ``getExtendedType`` function. It is used to indicate the name of the form type that will be +extended by your extension. + +.. tip:: + + The value you return in the ``getExtendedType`` method corresponds to the value returned by the ``getName`` method in the form type class + you wish to extend. + +In adition to the ``getExtendedType`` function, you will probably want to override one of the following methods : + +* ``buildForm()`` + +* ``buildView()`` + +* ``setDefaultOptions()`` + +For more information on what those methods do, you can refer to the :doc:`Creating Custom Field Types ` +cookbook article. + +Creating your Field Type as a Service +------------------------------------- + +The next step is to make Symfony aware of your form extension. All you need to do is to declare it as a service by +using the ``form.type_extension`` tag: + +.. configuration-block:: + + .. code-block:: yaml + + services: + acme_demo_bundle.image_type_extension: + class: Acme\DemoBundle\Form\Type\ImageTypeExtension + tags: + - { name: form.type_extension, alias: file } + + .. code-block:: xml + + + + + + .. code-block:: php + + $container + ->register('acme_demo_bundle.image_type_extension', 'Acme\DemoBundle\Form\Type\ImageTypeExtension') + ->addTag('form.type_extension', array('alias' => 'file')) + ; + +The ``alias`` key of the tag is the type of field that this extension should be applied to. In our case, as we +want to extend the ``file`` field type, we will use ``file`` as an alias. + +Adding the extension business logic +----------------------------------- + +The goal of our extension is to display a nice image next to file field types containing image files. For that +purpose, we will assume that we use an approach similar to the one described in +:doc:`How to handle File Uploads with Doctrine ` : we have a Media model with a file property +(corresponding to the file field in the form) and a path property (corresponding to the image path in the database). + +.. code-block:: php + + // src/Acme/DemoBundle/Entity/Media.php + namespace Acme\DemoBundle\Entity; + + use Doctrine\ORM\Mapping as ORM; + use Symfony\Component\Validator\Constraints as Assert; + + /** + * @ORM\Entity + * @ORM\Table + */ + class Media + { + + ... + + /** + * @var string + * + * @ORM\Column(name="path", type="string", length=255) + */ + private $path; + + /** + * @var \Symfony\Component\HttpFoundation\File\UploadedFile + * @Assert\File(maxSize="2M") + */ + public $file; + + ... + + /** + * Get the image url + * + * @return null|string + */ + public function getWebPath() + { + // return the full image url, to be used in templates for example + } + +Our field type extension class will need to do two things : + +1) Override the ``setDefaultOptions`` method in order to add an image_path option +2) Override the ``buildView`` method in order to pass the image url to the view + +The logic is the following : when adding a form field of type ``file``, we will be able to specify a new option : ``image_path``. +This option will tell the file field how to get the actual image url in order to display it in the view. + +.. code-block:: php + + // src/Acme/DemoBundle/Form/Type/ImageTypeExtension.php + namespace Acme\DemoBundle\Form\Type; + + use Symfony\Component\Form\AbstractTypeExtension; + use Symfony\Component\Form\FormTypeExtensionInterface; + use Symfony\Component\Form\FormView; + use Symfony\Component\Form\FormInterface; + use Symfony\Component\OptionsResolver\OptionsResolverInterface; + use Symfony\Component\Form\Util\PropertyPath; + + class ImageTypeExtension extends AbstractTypeExtension { + + /** + * Returns the name of the type being extended. + * + * @return string The name of the type being extended + */ + public function getExtendedType() + { + return 'file'; + } + + /** + * Add the image_path option + * + * @param \Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver + */ + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $resolver->setOptional(array('image_path')); + } + + /** + * Pass the image url to the view + * + * @param \Symfony\Component\Form\FormView $view + * @param \Symfony\Component\Form\FormInterface $form + * @param array $options + */ + public function buildView(FormView $view, FormInterface $form, array $options) + { + if (array_key_exists('image_path', $options)) { + $parentData = $form->getParent()->getData(); + + $propertyPath = new PropertyPath($options['image_path']); + $imageUrl = $propertyPath->getValue($parentData); + $view->set('image_url', $imageUrl); + } + } + + } + +Override the file widget template fragment +------------------------------------------ + +Each field type is rendered by a template fragment. Those template fragments can be overriden in order +to customize form rendering ; for more information, see :ref:`cookbook-form-customization-form-themes`. + +In our extension class, we have added a new variable (``image_url``), but we still need to take advantage of +this new variable in our templates. We need to override the ``file_widget`` block : + +.. code-block:: html+jinja + + {# src/Acme/DemoBundle/Resources/views/Form/fields.html.twig #} + {% extends 'form_div_layout.html.twig' %} + + {% block file_widget %} + {% spaceless %} + + {{ block('form_widget') }} + {% if image_url is not null %} + + {% endif %} + + {% endspaceless %} + {% endblock %} + +.. note:: + + You will need to change your config file or to explicitly specify how you want your form to be themed in order for + Symfony to use your overriden block. See :ref:`cookbook-form-customization-form-themes` for more information. + +Using the Field Type Extension +------------------------------ + +From now on, when adding a field of type ``file`` in your form, you can specify an ``image_path`` option that will be used to display +an image next to the file field. As an example : + +.. code-block:: php + + // src/Acme/DemoBundle/Form/Type/MediaType.php + namespace Acme\DemoBundle\Form; + + use Symfony\Component\Form\AbstractType; + use Symfony\Component\Form\FormBuilderInterface; + + class MediaType extends AbstractType + { + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add('name', 'text') + ->add('file', 'file', array('image_path' => 'webPath')); + } + + public function getName() + { + return 'media'; + } + } + +When displaying the form, if the underlying model has already been associated with an image, you will see it +displayed next to the file input. From 64e41fc06c1d09aa7f05d7187962f328c83e51cf Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Sun, 9 Sep 2012 16:40:49 +0200 Subject: [PATCH 02/10] Corrected to comply with symfony-docs standards (#814) --- cookbook/form/create_field_type_extension.rst | 133 ++++++++++-------- 1 file changed, 78 insertions(+), 55 deletions(-) diff --git a/cookbook/form/create_field_type_extension.rst b/cookbook/form/create_field_type_extension.rst index 6faa3f9c55b..dba8cd4f834 100644 --- a/cookbook/form/create_field_type_extension.rst +++ b/cookbook/form/create_field_type_extension.rst @@ -4,40 +4,51 @@ How to Create a Field Type Extension ====================================== -:doc:`Custom form field types ` are great when you need field types with a specific purpose, -such as a gender selector, or a VAT number input. +:doc:`Custom form field types ` are great when +you need field types with a specific purpose, such as a gender selector, +or a VAT number input. -But sometimes, you don't really need to add new field types - you want to add features on top of existing field types. -This is where Field Type Extensions come in. +But sometimes, you don't really need to add new field types - you want +to add features on top of existing field types. This is where Field Type +Extensions come in. Field Type Extensions have 2 main use cases : -#. You want to add a **generic feature to several field types** (such as adding a "help" field to every field type) -#. You want to add a **specific feature to a single field type** (such as adding a "download" feature to the "file" field type) +#. You want to add a **generic feature to several field types** (such as + adding a "help" field to every field type) +#. You want to add a **specific feature to a single field type** (such + as adding a "download" feature to the "file" field type) -In both those cases, it might be possible to achieve your goal with custom form rendering, or custom form field types. But using -field type extensions can be cleaner (by limiting the amount of business logic in templates) and more flexible (you can add several type extensions -to a single form type). +In both those cases, it might be possible to achieve your goal with custom +form rendering, or custom form field types. But using field type extensions +can be cleaner (by limiting the amount of business logic in templates) +and more flexible (you can add several type extensions to a single form +type). -Field Type Extensions can achieve most of what custom field types can do, but instead of being field types of their own, -**they plug into existing field types**. +Field Type Extensions can achieve most of what custom field types can do, +but instead of being field types of their own, **they plug into existing +field types**. -Imagine that you manage a ``Media`` entity, and that each media is associated to a file. Your ``Media`` form uses a file type, but when editing the entity, -you would like to see its image automatically rendered next to the file input. +Imagine that you manage a ``Media`` entity, and that each media is associated +to a file. Your ``Media`` form uses a file type, but when editing the entity, +you would like to see its image automatically rendered next to the file +input. -You could of course do by fine-tuning your edition form template. But form type extensions allow you to do this in a nice DRY fashion. +You could of course do by fine-tuning your edition form template. But form +type extensions allow you to do this in a nice DRY fashion. Defining the Field Type Extension --------------------------------- -Our first task will be to create the field type extension class. Let's call it ``ImageTypeExtension``. We will store the class in a file called +Our first task will be to create the field type extension class. Let's +call it ``ImageTypeExtension``. We will store the class in a file called ``ImageTypeExtension.php``, in the ``\Form\Type`` directory. -When creating a form type extension, you can either implements the :class:`Symfony\\Component\\Form\\FormTypeExtensionInterface` -interface, or extends the :class:`Symfony\\Component\\Form\\AbstractTypeExtension` class. Most of the time, you will -end up extending the abstract class ; that's what we will do in this tutorial. - -.. code-block:: php +When creating a form type extension, you can either implements the +:class:`Symfony\\Component\\Form\\FormTypeExtensionInterface` interface, +or extends the :class:`Symfony\\Component\\Form\\AbstractTypeExtension` +class. Most of the time, you will end up extending the abstract class ; +that's what we will do in this tutorial.:: // src/Acme/DemoBundle/Form/Type/ImageTypeExtension.php namespace Acme\DemoBundle\Form\Type; @@ -58,15 +69,18 @@ end up extending the abstract class ; that's what we will do in this tutorial. } -The only method you **must** implement is the ``getExtendedType`` function. It is used to indicate the name of the form type that will be -extended by your extension. +The only method you **must** implement is the ``getExtendedType`` function. +It is used to indicate the name of the form type that will be extended +by your extension. .. tip:: - The value you return in the ``getExtendedType`` method corresponds to the value returned by the ``getName`` method in the form type class + The value you return in the ``getExtendedType`` method corresponds + to the value returned by the ``getName`` method in the form type class you wish to extend. -In adition to the ``getExtendedType`` function, you will probably want to override one of the following methods : +In adition to the ``getExtendedType`` function, you will probably want +to override one of the following methods : * ``buildForm()`` @@ -74,14 +88,16 @@ In adition to the ``getExtendedType`` function, you will probably want to overri * ``setDefaultOptions()`` -For more information on what those methods do, you can refer to the :doc:`Creating Custom Field Types ` +For more information on what those methods do, you can refer to the +:doc:`Creating Custom Field Types ` cookbook article. Creating your Field Type as a Service ------------------------------------- -The next step is to make Symfony aware of your form extension. All you need to do is to declare it as a service by -using the ``form.type_extension`` tag: +The next step is to make Symfony aware of your form extension. All you +need to do is to declare it as a service by using the ``form.type_extension`` +tag : .. configuration-block:: @@ -106,18 +122,20 @@ using the ``form.type_extension`` tag: ->addTag('form.type_extension', array('alias' => 'file')) ; -The ``alias`` key of the tag is the type of field that this extension should be applied to. In our case, as we -want to extend the ``file`` field type, we will use ``file`` as an alias. +The ``alias`` key of the tag is the type of field that this extension should +be applied to. In our case, as we want to extend the ``file`` field type, +we will use ``file`` as an alias. Adding the extension business logic ----------------------------------- -The goal of our extension is to display a nice image next to file field types containing image files. For that -purpose, we will assume that we use an approach similar to the one described in -:doc:`How to handle File Uploads with Doctrine ` : we have a Media model with a file property -(corresponding to the file field in the form) and a path property (corresponding to the image path in the database). - -.. code-block:: php +The goal of our extension is to display a nice image next to file field +types containing image files. For that purpose, we will assume that we +use an approach similar to the one described in +:doc:`How to handle File Uploads with Doctrine ` : +we have a Media model with a file property (corresponding to the file field +in the form) and a path property (corresponding to the image path in the +database).:: // src/Acme/DemoBundle/Entity/Media.php namespace Acme\DemoBundle\Entity; @@ -132,7 +150,7 @@ purpose, we will assume that we use an approach similar to the one described in class Media { - ... + // ... /** * @var string @@ -147,7 +165,7 @@ purpose, we will assume that we use an approach similar to the one described in */ public $file; - ... + // ... /** * Get the image url @@ -161,13 +179,15 @@ purpose, we will assume that we use an approach similar to the one described in Our field type extension class will need to do two things : -1) Override the ``setDefaultOptions`` method in order to add an image_path option -2) Override the ``buildView`` method in order to pass the image url to the view +1) Override the ``setDefaultOptions`` method in order to add an image_path + option +2) Override the ``buildView`` method in order to pass the image url to + the view -The logic is the following : when adding a form field of type ``file``, we will be able to specify a new option : ``image_path``. -This option will tell the file field how to get the actual image url in order to display it in the view. - -.. code-block:: php +The logic is the following : when adding a form field of type ``file``, +we will be able to specify a new option : ``image_path``. This option will +tell the file field how to get the actual image url in order to display +it in the view.:: // src/Acme/DemoBundle/Form/Type/ImageTypeExtension.php namespace Acme\DemoBundle\Form\Type; @@ -224,11 +244,13 @@ This option will tell the file field how to get the actual image url in order to Override the file widget template fragment ------------------------------------------ -Each field type is rendered by a template fragment. Those template fragments can be overriden in order -to customize form rendering ; for more information, see :ref:`cookbook-form-customization-form-themes`. +Each field type is rendered by a template fragment. Those template fragments +can be overriden in order to customize form rendering ; for more information, +see :ref:`cookbook-form-customization-form-themes`. -In our extension class, we have added a new variable (``image_url``), but we still need to take advantage of -this new variable in our templates. We need to override the ``file_widget`` block : +In our extension class, we have added a new variable (``image_url``), but +we still need to take advantage of this new variable in our templates. +We need to override the ``file_widget`` block : .. code-block:: html+jinja @@ -248,16 +270,17 @@ this new variable in our templates. We need to override the ``file_widget`` bloc .. note:: - You will need to change your config file or to explicitly specify how you want your form to be themed in order for - Symfony to use your overriden block. See :ref:`cookbook-form-customization-form-themes` for more information. + You will need to change your config file or to explicitly specify how + you want your form to be themed in order for Symfony to use your overriden + block. See :ref:`cookbook-form-customization-form-themes` for more + information. Using the Field Type Extension ------------------------------ -From now on, when adding a field of type ``file`` in your form, you can specify an ``image_path`` option that will be used to display -an image next to the file field. As an example : - -.. code-block:: php +From now on, when adding a field of type ``file`` in your form, you can +specify an ``image_path`` option that will be used to display an image +next to the file field. As an example : :: // src/Acme/DemoBundle/Form/Type/MediaType.php namespace Acme\DemoBundle\Form; @@ -280,5 +303,5 @@ an image next to the file field. As an example : } } -When displaying the form, if the underlying model has already been associated with an image, you will see it -displayed next to the file input. +When displaying the form, if the underlying model has already been associated +with an image, you will see it displayed next to the file input. \ No newline at end of file From 0aae54dfcc6edc984e1b94c53069e06eefec83c1 Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Sun, 9 Sep 2012 19:28:43 +0200 Subject: [PATCH 03/10] Fixed examples to comply with symfony CS and mention finishView (#814) --- cookbook/form/create_field_type_extension.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cookbook/form/create_field_type_extension.rst b/cookbook/form/create_field_type_extension.rst index dba8cd4f834..ac32c0aaacb 100644 --- a/cookbook/form/create_field_type_extension.rst +++ b/cookbook/form/create_field_type_extension.rst @@ -56,7 +56,9 @@ that's what we will do in this tutorial.:: use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormTypeExtensionInterface; - class ImageTypeExtension extends AbstractTypeExtension { + class ImageTypeExtension extends AbstractTypeExtension + { + /** * Returns the name of the type being extended. * @@ -88,6 +90,8 @@ to override one of the following methods : * ``setDefaultOptions()`` +* ``finishView()`` + For more information on what those methods do, you can refer to the :doc:`Creating Custom Field Types ` cookbook article. @@ -199,7 +203,8 @@ it in the view.:: use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\Form\Util\PropertyPath; - class ImageTypeExtension extends AbstractTypeExtension { + class ImageTypeExtension extends AbstractTypeExtension + { /** * Returns the name of the type being extended. @@ -290,6 +295,7 @@ next to the file field. As an example : :: class MediaType extends AbstractType { + public function buildForm(FormBuilderInterface $builder, array $options) { $builder From f6fa37c0d01cf95fec7bb03a953e40307a7ea50c Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Tue, 11 Sep 2012 08:37:38 +0200 Subject: [PATCH 04/10] Added some more CS-related corrections (#814) --- cookbook/form/create_field_type_extension.rst | 57 +++++++++++-------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/cookbook/form/create_field_type_extension.rst b/cookbook/form/create_field_type_extension.rst index ac32c0aaacb..a3cd8141174 100644 --- a/cookbook/form/create_field_type_extension.rst +++ b/cookbook/form/create_field_type_extension.rst @@ -4,7 +4,7 @@ How to Create a Field Type Extension ====================================== -:doc:`Custom form field types ` are great when +:doc:`Custom form field types` are great when you need field types with a specific purpose, such as a gender selector, or a VAT number input. @@ -12,7 +12,7 @@ But sometimes, you don't really need to add new field types - you want to add features on top of existing field types. This is where Field Type Extensions come in. -Field Type Extensions have 2 main use cases : +Field Type Extensions have 2 main use cases: #. You want to add a **generic feature to several field types** (such as adding a "help" field to every field type) @@ -48,7 +48,9 @@ When creating a form type extension, you can either implements the :class:`Symfony\\Component\\Form\\FormTypeExtensionInterface` interface, or extends the :class:`Symfony\\Component\\Form\\AbstractTypeExtension` class. Most of the time, you will end up extending the abstract class ; -that's what we will do in this tutorial.:: +that's what we will do in this tutorial. + +.. code-block:: php // src/Acme/DemoBundle/Form/Type/ImageTypeExtension.php namespace Acme\DemoBundle\Form\Type; @@ -82,7 +84,7 @@ by your extension. you wish to extend. In adition to the ``getExtendedType`` function, you will probably want -to override one of the following methods : +to override one of the following methods: * ``buildForm()`` @@ -93,7 +95,7 @@ to override one of the following methods : * ``finishView()`` For more information on what those methods do, you can refer to the -:doc:`Creating Custom Field Types ` +:doc:`Creating Custom Field Types` cookbook article. Creating your Field Type as a Service @@ -101,7 +103,7 @@ Creating your Field Type as a Service The next step is to make Symfony aware of your form extension. All you need to do is to declare it as a service by using the ``form.type_extension`` -tag : +tag: .. configuration-block:: @@ -123,8 +125,7 @@ tag : $container ->register('acme_demo_bundle.image_type_extension', 'Acme\DemoBundle\Form\Type\ImageTypeExtension') - ->addTag('form.type_extension', array('alias' => 'file')) - ; + ->addTag('form.type_extension', array('alias' => 'file')); The ``alias`` key of the tag is the type of field that this extension should be applied to. In our case, as we want to extend the ``file`` field type, @@ -136,10 +137,12 @@ Adding the extension business logic The goal of our extension is to display a nice image next to file field types containing image files. For that purpose, we will assume that we use an approach similar to the one described in -:doc:`How to handle File Uploads with Doctrine ` : +:doc:`How to handle File Uploads with Doctrine`: we have a Media model with a file property (corresponding to the file field in the form) and a path property (corresponding to the image path in the -database).:: +database). + +.. code-block:: php // src/Acme/DemoBundle/Entity/Media.php namespace Acme\DemoBundle\Entity; @@ -178,20 +181,24 @@ database).:: */ public function getWebPath() { - // return the full image url, to be used in templates for example + // ... $webPath being the full image url, to be used in templates + + return $webPath; } -Our field type extension class will need to do two things : +Our field type extension class will need to do two things: 1) Override the ``setDefaultOptions`` method in order to add an image_path option 2) Override the ``buildView`` method in order to pass the image url to the view -The logic is the following : when adding a form field of type ``file``, -we will be able to specify a new option : ``image_path``. This option will +The logic is the following: when adding a form field of type ``file``, +we will be able to specify a new option: ``image_path``. This option will tell the file field how to get the actual image url in order to display -it in the view.:: +it in the view. + +.. code-block:: php // src/Acme/DemoBundle/Form/Type/ImageTypeExtension.php namespace Acme\DemoBundle\Form\Type; @@ -229,9 +236,9 @@ it in the view.:: /** * Pass the image url to the view * - * @param \Symfony\Component\Form\FormView $view + * @param \Symfony\Component\Form\FormView $view * @param \Symfony\Component\Form\FormInterface $form - * @param array $options + * @param array $options */ public function buildView(FormView $view, FormInterface $form, array $options) { @@ -255,7 +262,7 @@ see :ref:`cookbook-form-customization-form-themes`. In our extension class, we have added a new variable (``image_url``), but we still need to take advantage of this new variable in our templates. -We need to override the ``file_widget`` block : +We need to override the ``file_widget`` block: .. code-block:: html+jinja @@ -263,14 +270,14 @@ We need to override the ``file_widget`` block : {% extends 'form_div_layout.html.twig' %} {% block file_widget %} - {% spaceless %} + {% spaceless %} - {{ block('form_widget') }} - {% if image_url is not null %} - - {% endif %} + {{ block('form_widget') }} + {% if image_url is not null %} + + {% endif %} - {% endspaceless %} + {% endspaceless %} {% endblock %} .. note:: @@ -285,7 +292,7 @@ Using the Field Type Extension From now on, when adding a field of type ``file`` in your form, you can specify an ``image_path`` option that will be used to display an image -next to the file field. As an example : :: +next to the file field. As an example:: // src/Acme/DemoBundle/Form/Type/MediaType.php namespace Acme\DemoBundle\Form; From 2b6bbee516974762fc8a52a7d996fe8f2f173170 Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Sun, 16 Sep 2012 11:32:14 +0200 Subject: [PATCH 05/10] Fixed a few typos and formatting errors (#814) --- cookbook/form/create_field_type_extension.rst | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/cookbook/form/create_field_type_extension.rst b/cookbook/form/create_field_type_extension.rst index a3cd8141174..f8df06093c3 100644 --- a/cookbook/form/create_field_type_extension.rst +++ b/cookbook/form/create_field_type_extension.rst @@ -2,7 +2,7 @@ single: Form; Field type extension How to Create a Field Type Extension -====================================== +==================================== :doc:`Custom form field types` are great when you need field types with a specific purpose, such as a gender selector, @@ -34,7 +34,7 @@ to a file. Your ``Media`` form uses a file type, but when editing the entity, you would like to see its image automatically rendered next to the file input. -You could of course do by fine-tuning your edition form template. But form +You could of course do this by customizing how this field is rendered in a template. But form type extensions allow you to do this in a nice DRY fashion. Defining the Field Type Extension @@ -44,13 +44,11 @@ Our first task will be to create the field type extension class. Let's call it ``ImageTypeExtension``. We will store the class in a file called ``ImageTypeExtension.php``, in the ``\Form\Type`` directory. -When creating a form type extension, you can either implements the +When creating a form type extension, you can either implement the :class:`Symfony\\Component\\Form\\FormTypeExtensionInterface` interface, -or extends the :class:`Symfony\\Component\\Form\\AbstractTypeExtension` -class. Most of the time, you will end up extending the abstract class ; -that's what we will do in this tutorial. - -.. code-block:: php +or extend the :class:`Symfony\\Component\\Form\\AbstractTypeExtension` +class. Most of the time, you will end up extending the abstract class; +that's what we will do in this tutorial:: // src/Acme/DemoBundle/Form/Type/ImageTypeExtension.php namespace Acme\DemoBundle\Form\Type; @@ -83,7 +81,7 @@ by your extension. to the value returned by the ``getName`` method in the form type class you wish to extend. -In adition to the ``getExtendedType`` function, you will probably want +In addition to the ``getExtendedType`` function, you will probably want to override one of the following methods: * ``buildForm()`` @@ -257,7 +255,7 @@ Override the file widget template fragment ------------------------------------------ Each field type is rendered by a template fragment. Those template fragments -can be overriden in order to customize form rendering ; for more information, +can be overridden in order to customize form rendering; for more information, see :ref:`cookbook-form-customization-form-themes`. In our extension class, we have added a new variable (``image_url``), but @@ -283,7 +281,7 @@ We need to override the ``file_widget`` block: .. note:: You will need to change your config file or to explicitly specify how - you want your form to be themed in order for Symfony to use your overriden + you want your form to be themed in order for Symfony to use your overridden block. See :ref:`cookbook-form-customization-form-themes` for more information. From 71d2dae4580c32cea8bfb54cc0a2165d84b445ee Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Sun, 16 Sep 2012 11:35:53 +0200 Subject: [PATCH 06/10] Added "create_field_type_extension" in map and from index (#814) --- cookbook/form/index.rst | 1 + cookbook/map.rst.inc | 1 + 2 files changed, 2 insertions(+) diff --git a/cookbook/form/index.rst b/cookbook/form/index.rst index 1dba8aa6f98..25acd23a6e7 100644 --- a/cookbook/form/index.rst +++ b/cookbook/form/index.rst @@ -9,4 +9,5 @@ Form dynamic_form_generation form_collections create_custom_field_type + create_field_type_extension use_virtuals_forms diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index bb8551345cc..3531ff9d0d9 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -72,6 +72,7 @@ * :doc:`/cookbook/form/dynamic_form_generation` * :doc:`/cookbook/form/form_collections` * :doc:`/cookbook/form/create_custom_field_type` + * :doc:`/cookbook/form/create_field_type_extension` * :doc:`/cookbook/form/use_virtuals_forms` * (validation) :doc:`/cookbook/validation/custom_constraint` * (doctrine) :doc:`/cookbook/doctrine/file_uploads` From 8cf7b82ecec1f33db3af3e4a7b7f47b809d12022 Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Wed, 19 Sep 2012 00:09:22 +0200 Subject: [PATCH 07/10] Changed the text so that it uses the first person plural, rephrased a few sentences and corrected typos (#814) --- cookbook/form/create_field_type_extension.rst | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/cookbook/form/create_field_type_extension.rst b/cookbook/form/create_field_type_extension.rst index f8df06093c3..4a76b73d8ea 100644 --- a/cookbook/form/create_field_type_extension.rst +++ b/cookbook/form/create_field_type_extension.rst @@ -9,13 +9,13 @@ you need field types with a specific purpose, such as a gender selector, or a VAT number input. But sometimes, you don't really need to add new field types - you want -to add features on top of existing field types. This is where Field Type -Extensions come in. +to add features on top of existing field types. This is where field type +extensions come in. -Field Type Extensions have 2 main use cases: +Field type extensions have 2 main use cases: #. You want to add a **generic feature to several field types** (such as - adding a "help" field to every field type) + adding a "help" text to every field type) #. You want to add a **specific feature to a single field type** (such as adding a "download" feature to the "file" field type) @@ -25,7 +25,7 @@ can be cleaner (by limiting the amount of business logic in templates) and more flexible (you can add several type extensions to a single form type). -Field Type Extensions can achieve most of what custom field types can do, +Field type extensions can achieve most of what custom field types can do, but instead of being field types of their own, **they plug into existing field types**. @@ -34,27 +34,26 @@ to a file. Your ``Media`` form uses a file type, but when editing the entity, you would like to see its image automatically rendered next to the file input. -You could of course do this by customizing how this field is rendered in a template. But form +You could of course do this by customizing how this field is rendered in a template. But field type extensions allow you to do this in a nice DRY fashion. Defining the Field Type Extension --------------------------------- -Our first task will be to create the field type extension class. Let's -call it ``ImageTypeExtension``. We will store the class in a file called +Your first task will be to create the field type extension class. Let's +call it ``ImageTypeExtension``. You will store the class in a file called ``ImageTypeExtension.php``, in the ``\Form\Type`` directory. -When creating a form type extension, you can either implement the +When creating a field type extension, you can either implement the :class:`Symfony\\Component\\Form\\FormTypeExtensionInterface` interface, or extend the :class:`Symfony\\Component\\Form\\AbstractTypeExtension` -class. Most of the time, you will end up extending the abstract class; -that's what we will do in this tutorial:: +class. Most of the time, you will end up extending the abstract class. +That's what you will do in this tutorial:: // src/Acme/DemoBundle/Form/Type/ImageTypeExtension.php namespace Acme\DemoBundle\Form\Type; use Symfony\Component\Form\AbstractTypeExtension; - use Symfony\Component\Form\FormTypeExtensionInterface; class ImageTypeExtension extends AbstractTypeExtension { @@ -96,10 +95,10 @@ For more information on what those methods do, you can refer to the :doc:`Creating Custom Field Types` cookbook article. -Creating your Field Type as a Service -------------------------------------- +Registering your Field Type Extension as a Service +-------------------------------------------------- -The next step is to make Symfony aware of your form extension. All you +The next step is to make Symfony aware of your extension. All you need to do is to declare it as a service by using the ``form.type_extension`` tag: @@ -126,17 +125,17 @@ tag: ->addTag('form.type_extension', array('alias' => 'file')); The ``alias`` key of the tag is the type of field that this extension should -be applied to. In our case, as we want to extend the ``file`` field type, -we will use ``file`` as an alias. +be applied to. In your case, as you want to extend the ``file`` field type, +you will use ``file`` as an alias. Adding the extension business logic ----------------------------------- -The goal of our extension is to display a nice image next to file field -types containing image files. For that purpose, we will assume that we -use an approach similar to the one described in +The goal of your extension is to display a nice image next to file inputs +(when the underlying model contains images). For that purpose, let's assume +that you use an approach similar to the one described in :doc:`How to handle File Uploads with Doctrine`: -we have a Media model with a file property (corresponding to the file field +you have a Media model with a file property (corresponding to the file field in the form) and a path property (corresponding to the image path in the database). @@ -184,7 +183,7 @@ database). return $webPath; } -Our field type extension class will need to do two things: +Your field type extension class will need to do two things: 1) Override the ``setDefaultOptions`` method in order to add an image_path option @@ -192,7 +191,7 @@ Our field type extension class will need to do two things: the view The logic is the following: when adding a form field of type ``file``, -we will be able to specify a new option: ``image_path``. This option will +you will be able to specify a new option: ``image_path``. This option will tell the file field how to get the actual image url in order to display it in the view. @@ -202,7 +201,6 @@ it in the view. namespace Acme\DemoBundle\Form\Type; use Symfony\Component\Form\AbstractTypeExtension; - use Symfony\Component\Form\FormTypeExtensionInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; @@ -256,11 +254,11 @@ Override the file widget template fragment Each field type is rendered by a template fragment. Those template fragments can be overridden in order to customize form rendering; for more information, -see :ref:`cookbook-form-customization-form-themes`. +you can refer to the :ref:`cookbook-form-customization-form-themes` article. -In our extension class, we have added a new variable (``image_url``), but -we still need to take advantage of this new variable in our templates. -We need to override the ``file_widget`` block: +In your extension class, you have added a new variable (``image_url``), but +you still need to take advantage of this new variable in your templates. +You need to override the ``file_widget`` block: .. code-block:: html+jinja From 6cf24a93a6810869c98e2c1a0d7b7c9322821b38 Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Sat, 6 Oct 2012 18:54:32 +0200 Subject: [PATCH 08/10] Changed "field type extension" to "form type extension" (#814) --- ...ion.rst => create_form_type_extension.rst} | 31 +++++++++---------- cookbook/form/index.rst | 2 +- cookbook/map.rst.inc | 2 +- 3 files changed, 17 insertions(+), 18 deletions(-) rename cookbook/form/{create_field_type_extension.rst => create_form_type_extension.rst} (91%) diff --git a/cookbook/form/create_field_type_extension.rst b/cookbook/form/create_form_type_extension.rst similarity index 91% rename from cookbook/form/create_field_type_extension.rst rename to cookbook/form/create_form_type_extension.rst index 4a76b73d8ea..993e16f5520 100644 --- a/cookbook/form/create_field_type_extension.rst +++ b/cookbook/form/create_form_type_extension.rst @@ -1,7 +1,7 @@ .. index:: - single: Form; Field type extension + single: Form; Form type extension -How to Create a Field Type Extension +How to Create a Form Type Extension ==================================== :doc:`Custom form field types` are great when @@ -9,25 +9,24 @@ you need field types with a specific purpose, such as a gender selector, or a VAT number input. But sometimes, you don't really need to add new field types - you want -to add features on top of existing field types. This is where field type +to add features on top of existing types. This is where form type extensions come in. -Field type extensions have 2 main use cases: +Form type extensions have 2 main use cases: -#. You want to add a **generic feature to several field types** (such as +#. You want to add a **generic feature to several types** (such as adding a "help" text to every field type) -#. You want to add a **specific feature to a single field type** (such +#. You want to add a **specific feature to a single type** (such as adding a "download" feature to the "file" field type) In both those cases, it might be possible to achieve your goal with custom -form rendering, or custom form field types. But using field type extensions +form rendering, or custom form field types. But using form type extensions can be cleaner (by limiting the amount of business logic in templates) and more flexible (you can add several type extensions to a single form type). -Field type extensions can achieve most of what custom field types can do, -but instead of being field types of their own, **they plug into existing -field types**. +Form type extensions can achieve most of what custom field types can do, +but instead of being field types of their own, **they plug into existing types**. Imagine that you manage a ``Media`` entity, and that each media is associated to a file. Your ``Media`` form uses a file type, but when editing the entity, @@ -37,14 +36,14 @@ input. You could of course do this by customizing how this field is rendered in a template. But field type extensions allow you to do this in a nice DRY fashion. -Defining the Field Type Extension +Defining the Form Type Extension --------------------------------- -Your first task will be to create the field type extension class. Let's +Your first task will be to create the form type extension class. Let's call it ``ImageTypeExtension``. You will store the class in a file called ``ImageTypeExtension.php``, in the ``\Form\Type`` directory. -When creating a field type extension, you can either implement the +When creating a form type extension, you can either implement the :class:`Symfony\\Component\\Form\\FormTypeExtensionInterface` interface, or extend the :class:`Symfony\\Component\\Form\\AbstractTypeExtension` class. Most of the time, you will end up extending the abstract class. @@ -95,7 +94,7 @@ For more information on what those methods do, you can refer to the :doc:`Creating Custom Field Types` cookbook article. -Registering your Field Type Extension as a Service +Registering your Form Type Extension as a Service -------------------------------------------------- The next step is to make Symfony aware of your extension. All you @@ -183,7 +182,7 @@ database). return $webPath; } -Your field type extension class will need to do two things: +Your form type extension class will need to do two things: 1) Override the ``setDefaultOptions`` method in order to add an image_path option @@ -283,7 +282,7 @@ You need to override the ``file_widget`` block: block. See :ref:`cookbook-form-customization-form-themes` for more information. -Using the Field Type Extension +Using the Form Type Extension ------------------------------ From now on, when adding a field of type ``file`` in your form, you can diff --git a/cookbook/form/index.rst b/cookbook/form/index.rst index 25acd23a6e7..e60f02c9a68 100644 --- a/cookbook/form/index.rst +++ b/cookbook/form/index.rst @@ -9,5 +9,5 @@ Form dynamic_form_generation form_collections create_custom_field_type - create_field_type_extension + create_form_type_extension use_virtuals_forms diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 3531ff9d0d9..c7d863608ea 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -72,7 +72,7 @@ * :doc:`/cookbook/form/dynamic_form_generation` * :doc:`/cookbook/form/form_collections` * :doc:`/cookbook/form/create_custom_field_type` - * :doc:`/cookbook/form/create_field_type_extension` + * :doc:`/cookbook/form/create_form_type_extension` * :doc:`/cookbook/form/use_virtuals_forms` * (validation) :doc:`/cookbook/validation/custom_constraint` * (doctrine) :doc:`/cookbook/doctrine/file_uploads` From da066fc5cdfe5c1e96e04e9f2ed2fa39271960de Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Fri, 12 Oct 2012 09:37:40 +0200 Subject: [PATCH 09/10] [#814] [Form] Fine-tuned punctuations and style --- cookbook/form/create_form_type_extension.rst | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/cookbook/form/create_form_type_extension.rst b/cookbook/form/create_form_type_extension.rst index 993e16f5520..a2a97335e2a 100644 --- a/cookbook/form/create_form_type_extension.rst +++ b/cookbook/form/create_form_type_extension.rst @@ -15,9 +15,9 @@ extensions come in. Form type extensions have 2 main use cases: #. You want to add a **generic feature to several types** (such as - adding a "help" text to every field type) + adding a "help" text to every field type); #. You want to add a **specific feature to a single type** (such - as adding a "download" feature to the "file" field type) + as adding a "download" feature to the "file" field type). In both those cases, it might be possible to achieve your goal with custom form rendering, or custom form field types. But using form type extensions @@ -56,7 +56,6 @@ That's what you will do in this tutorial:: class ImageTypeExtension extends AbstractTypeExtension { - /** * Returns the name of the type being extended. * @@ -152,7 +151,6 @@ database). */ class Media { - // ... /** @@ -184,10 +182,10 @@ database). Your form type extension class will need to do two things: -1) Override the ``setDefaultOptions`` method in order to add an image_path - option -2) Override the ``buildView`` method in order to pass the image url to - the view +#. Override the ``setDefaultOptions`` method in order to add an image_path + option; +#. Override the ``buildView`` method in order to pass the image url to + the view. The logic is the following: when adding a form field of type ``file``, you will be able to specify a new option: ``image_path``. This option will @@ -207,7 +205,6 @@ it in the view. class ImageTypeExtension extends AbstractTypeExtension { - /** * Returns the name of the type being extended. * @@ -297,7 +294,6 @@ next to the file field. As an example:: class MediaType extends AbstractType { - public function buildForm(FormBuilderInterface $builder, array $options) { $builder From 47e01460b3b77d4cdcfea482a449c1ea7cb07f88 Mon Sep 17 00:00:00 2001 From: pvanliefland Date: Fri, 12 Oct 2012 11:19:38 +0200 Subject: [PATCH 10/10] [#814] [Form] Added html+php syntax --- cookbook/form/create_form_type_extension.rst | 32 +++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/cookbook/form/create_form_type_extension.rst b/cookbook/form/create_form_type_extension.rst index a2a97335e2a..e5ce03fdc07 100644 --- a/cookbook/form/create_form_type_extension.rst +++ b/cookbook/form/create_form_type_extension.rst @@ -256,21 +256,31 @@ In your extension class, you have added a new variable (``image_url``), but you still need to take advantage of this new variable in your templates. You need to override the ``file_widget`` block: -.. code-block:: html+jinja +.. configuration-block:: + + .. code-block:: html+jinja + + {# src/Acme/DemoBundle/Resources/views/Form/fields.html.twig #} + {% extends 'form_div_layout.html.twig' %} + + {% block file_widget %} + {% spaceless %} - {# src/Acme/DemoBundle/Resources/views/Form/fields.html.twig #} - {% extends 'form_div_layout.html.twig' %} + {{ block('form_widget') }} + {% if image_url is not null %} + + {% endif %} - {% block file_widget %} - {% spaceless %} + {% endspaceless %} + {% endblock %} - {{ block('form_widget') }} - {% if image_url is not null %} - - {% endif %} + .. code-block:: html+php - {% endspaceless %} - {% endblock %} + + widget($form) ?> + + + .. note::