@@ -7,7 +7,7 @@ How to Create a Custom Form Field Type
7
7
Symfony comes with a bunch of core field types available for building forms.
8
8
However there are situations where you may want to create a custom form field
9
9
type for a specific purpose. This recipe assumes you need a field definition
10
- that holds a person's gender , based on the existing choice field. This section
10
+ that holds a shipping option , based on the existing choice field. This section
11
11
explains how the field is defined, how you can customize its layout and finally,
12
12
how you can register it for use in your application.
13
13
@@ -16,25 +16,26 @@ Defining the Field Type
16
16
17
17
In order to create the custom field type, first you have to create the class
18
18
representing the field. In this situation the class holding the field type
19
- will be called ``GenderType `` and the file will be stored in the default location
19
+ will be called ``ShippingType `` and the file will be stored in the default location
20
20
for form fields, which is ``<BundleName>\Form\Type ``. Make sure the field extends
21
21
:class: `Symfony\\ Component\\ Form\\ AbstractType `::
22
22
23
- // src/AppBundle/Form/Type/GenderType .php
23
+ // src/AppBundle/Form/Type/ShippingType .php
24
24
namespace AppBundle\Form\Type;
25
25
26
26
use Symfony\Component\Form\AbstractType;
27
27
use Symfony\Component\OptionsResolver\OptionsResolver;
28
28
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
29
29
30
- class GenderType extends AbstractType
30
+ class ShippingType extends AbstractType
31
31
{
32
32
public function configureOptions(OptionsResolver $resolver)
33
33
{
34
34
$resolver->setDefaults(array(
35
35
'choices' => array(
36
- 'm' => 'Male',
37
- 'f' => 'Female',
36
+ 'Standard Shipping' => 'standard',
37
+ 'Expedited Shipping' => 'expedited',
38
+ 'Priority Shipping' => 'priority',
38
39
)
39
40
));
40
41
}
@@ -67,8 +68,8 @@ important:
67
68
This method is used to set any extra variables you'll
68
69
need when rendering your field in a template. For example, in `ChoiceType `_,
69
70
a ``multiple `` variable is set and used in the template to set (or not
70
- set) the ``multiple `` attribute on the ``select `` field. See ` Creating a Template for the Field `_
71
- for more details.
71
+ set) the ``multiple `` attribute on the ``select `` field. See
72
+ ` Creating a Template for the Field `_ for more details.
72
73
73
74
``configureOptions() ``
74
75
This defines options for your form type that
@@ -83,9 +84,9 @@ important:
83
84
Also, if you need to modify the "view" of any of your child types from
84
85
your parent type, use the ``finishView() `` method.
85
86
86
- The goal of this field was to extend the choice type to enable selection of
87
- a gender . This is achieved by fixing the ``choices `` to a list of possible
88
- genders .
87
+ The goal of this field was to extend the choice type to enable selection of the
88
+ shipping type . This is achieved by fixing the ``choices `` to a list of available
89
+ shipping options .
89
90
90
91
Creating a Template for the Field
91
92
---------------------------------
@@ -95,9 +96,9 @@ the class name of your type. For more information, see :ref:`form-customization-
95
96
96
97
.. note ::
97
98
98
- The first part of the prefix (e.g. ``gender ``) comes from the class name
99
- (``GenderType `` -> ``gender ``). This can be controlled by overriding ``getBlockPrefix() ``
100
- in ``GenderType ``.
99
+ The first part of the prefix (e.g. ``shipping ``) comes from the class name
100
+ (``ShippingType `` -> ``shipping ``). This can be controlled by overriding ``getBlockPrefix() ``
101
+ in ``ShippingType ``.
101
102
102
103
.. caution ::
103
104
@@ -113,14 +114,14 @@ any work as the custom field type will automatically be rendered like a ``Choice
113
114
But for the sake of this example, suppose that when your field is "expanded"
114
115
(i.e. radio buttons or checkboxes, instead of a select field), you want to
115
116
always render it in a ``ul `` element. In your form theme template (see above
116
- link for details), create a ``gender_widget `` block to handle this:
117
+ link for details), create a ``shipping_widget `` block to handle this:
117
118
118
119
.. configuration-block ::
119
120
120
121
.. code-block :: html+twig
121
122
122
123
{# app/Resources/views/form/fields.html.twig #}
123
- {% block gender_widget %}
124
+ {% block shipping_widget %}
124
125
{% spaceless %}
125
126
{% if expanded %}
126
127
<ul {{ block('widget_container_attributes') }}>
@@ -140,7 +141,7 @@ link for details), create a ``gender_widget`` block to handle this:
140
141
141
142
.. code-block :: html+php
142
143
143
- <!-- app/Resources/views/form/gender_widget .html.php -->
144
+ <!-- app/Resources/views/form/shipping_widget .html.php -->
144
145
<?php if ($expanded) : ?>
145
146
<ul <?php $view['form']->block($form, 'widget_container_attributes') ?>>
146
147
<?php foreach ($form as $child) : ?>
@@ -158,7 +159,7 @@ link for details), create a ``gender_widget`` block to handle this:
158
159
.. note ::
159
160
160
161
Make sure the correct widget prefix is used. In this example the name should
161
- be ``gender_widget `` (see :ref: `form-customization-form-themes `).
162
+ be ``shipping_widget `` (see :ref: `form-customization-form-themes `).
162
163
Further, the main config file should point to the custom form template
163
164
so that it's used when rendering all forms.
164
165
@@ -255,20 +256,20 @@ new instance of the type in one of your forms::
255
256
256
257
use Symfony\Component\Form\AbstractType;
257
258
use Symfony\Component\Form\FormBuilderInterface;
258
- use AppBundle\Form\Type\GenderType ;
259
+ use AppBundle\Form\Type\ShippingType ;
259
260
260
- class AuthorType extends AbstractType
261
+ class OrderType extends AbstractType
261
262
{
262
263
public function buildForm(FormBuilderInterface $builder, array $options)
263
264
{
264
- $builder->add('gender_code ', GenderType ::class, array(
265
- 'placeholder' => 'Choose a gender ',
265
+ $builder->add('shipping_code ', ShippingType ::class, array(
266
+ 'placeholder' => 'Choose a delivery option ',
266
267
));
267
268
}
268
269
}
269
270
270
- But this only works because the ``GenderType `` is very simple. What if
271
- the gender codes were stored in configuration or in a database? The next
271
+ But this only works because the ``ShippingType() `` is very simple. What if
272
+ the shipping codes were stored in configuration or in a database? The next
272
273
section explains how more complex field types solve this problem.
273
274
274
275
.. _form-field-service :
@@ -280,13 +281,13 @@ Accessing Services and Config
280
281
If you need to access :doc: `services </service_container >` from your form class,
281
282
add a ``__construct() `` method like normal::
282
283
283
- // src/AppBundle/Form/Type/GenderType .php
284
+ // src/AppBundle/Form/Type/ShippingType .php
284
285
namespace AppBundle\Form\Type;
285
286
286
287
// ...
287
288
use Doctrine\ORM\EntityManagerInterface;
288
289
289
- class GenderType extends AbstractType
290
+ class ShippingType extends AbstractType
290
291
{
291
292
private $em;
292
293
0 commit comments