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

Appearance settings

Commit 6da211f

Browse filesBrowse files
committed
[Form] Fix ChoiceType options
1 parent e7246b6 commit 6da211f
Copy full SHA for 6da211f

File tree

Expand file treeCollapse file tree

7 files changed

+191
-78
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+191
-78
lines changed

‎reference/forms/types/choice.rst

Copy file name to clipboardExpand all lines: reference/forms/types/choice.rst
+81-32Lines changed: 81 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,21 @@ This will create a ``select`` drop-down like this:
7070
.. image:: /images/reference/form/choice-example1.png
7171
:align: center
7272

73-
If the user selects ``No``, the form will return ``false`` for this field. Similarly,
74-
if the starting data for this field is ``true``, then ``Yes`` will be auto-selected.
75-
In other words, the **value** of each item is the value you want to get/set in PHP
76-
code, while the **key** is what will be shown to the user.
73+
The model data of this field, the **choice** may be any of the ``choices`` option
74+
values, while **keys** are used as default label that the user will see and select.
75+
If the user selects ``No``, the form will return a string representation of that
76+
choice, a string **value** (html attribute) which is by default the **choice** data
77+
casted to string.
78+
Hence, when choices are objects, either they should implement ``__toString()``
79+
method or the option ``choice_value`` should be defined.
80+
When the **choices** cannot be casted to string or when ``choice_value`` returns
81+
either ``null`` or non unique values an incrementing integer is used as **value**.
82+
83+
If the starting data for this field is ``true``, then ``Yes`` will be auto-selected.
84+
In other words, each value of the ``choices`` option is the **choice** data you
85+
want to deal with in PHP code, while the **key** is the default label that will be
86+
shown to the user and the **value** is the string that will be submitted to the
87+
form and used in the template for the corresponding html attribute.
7788

7889
.. caution::
7990

@@ -83,40 +94,68 @@ code, while the **key** is what will be shown to the user.
8394
and will be removed in 3.0. To read about the old API, read an older version of
8495
the docs.
8596

97+
.. note::
98+
99+
Pre selected choices will depend on the **data** passed to field and the values of
100+
the ``choices`` option. However submitted choices will depend on the **string**
101+
matching the **choice**. In the example above, the default values falls back on an
102+
incrementing integer because ``null`` cannot be casted to string.
103+
You should consider it as well when dealing with ``emtpy_data`` option::
104+
105+
$builder->add('isAttending', 'choice', array(
106+
'choices' => array(
107+
'Maybe' => null,
108+
'Yes' => true,
109+
'No' => false,
110+
),
111+
'choices_as_values' => true,
112+
'data' => true, // pre selected choice
113+
'empty_data' => '1', // default submitted value
114+
));
115+
116+
Also note that as a ``scalar``, ``false`` string **value** is by default ``"0"``
117+
to avoid conflict with placeholder value which is always an empty string.
118+
86119
Advanced Example (with Objects!)
87120
--------------------------------
88121

89122
This field has a *lot* of options and most control how the field is displayed. In
90123
this example, the underlying data is some ``Category`` object that has a ``getName()``
91124
method::
92125

93-
$builder->add('category', 'choice', [
94-
'choices' => [
126+
$builder->add('category', 'choice', array(
127+
'choices' => array(
95128
new Category('Cat1'),
96129
new Category('Cat2'),
97130
new Category('Cat3'),
98131
new Category('Cat4'),
99-
],
132+
),
100133
'choices_as_values' => true,
101-
'choice_label' => function($category, $key, $index) {
134+
'choice_label' => function($category, $key, $value) {
102135
/** @var Category $category */
103136
return strtoupper($category->getName());
104137
},
105-
'choice_attr' => function($category, $key, $index) {
106-
return ['class' => 'category_'.strtolower($category->getName())];
138+
'choice_attr' => function($category, $key, $value) {
139+
return array('class' => 'category_'.strtolower($category->getName()));
107140
},
108-
'group_by' => function($category, $key, $index) {
141+
'group_by' => function($category, $key, $value) {
109142
// randomly assign things into 2 groups
110143
return rand(0, 1) == 1 ? 'Group A' : 'Group B'
111144
},
112-
'preferred_choices' => function($category, $key, $index) {
145+
'preferred_choices' => function($category, $key, $value) {
113146
return $category->getName() == 'Cat2' || $category->getName() == 'Cat3';
114147
},
115-
]);
148+
));
116149

117150
You can also customize the `choice_name`_ and `choice_value`_ of each choice if
118151
you need further HTML customization.
119152

153+
.. caution::
154+
155+
We avoid type hinting ``Category`` in this example as it may conflict
156+
if the placeholder is passed, also you should test whether ``$choice``
157+
is ``null`` before calling any method or object property.
158+
120159
.. _forms-reference-choice-tags:
121160

122161
.. include:: /reference/forms/types/options/select_how_rendered.rst.inc
@@ -135,19 +174,19 @@ Grouping Options
135174

136175
You can easily "group" options in a select by passing a multi-dimensional choices array::
137176

138-
$builder->add('stockStatus', 'choice', [
139-
'choices' => [
140-
'Main Statuses' => [
177+
$builder->add('stockStatus', 'choice', array(
178+
'choices' => array(
179+
'Main Statuses' => array(
141180
'Yes' => 'stock_yes',
142181
'No' => 'stock_no',
143-
],
144-
'Out of Stock Statuses' => [
182+
),
183+
'Out of Stock Statuses' => array(
145184
'Backordered' => 'stock_backordered',
146185
'Discontinued' => 'stock_discontinued',
147-
]
148-
],
186+
),
187+
),
149188
'choices_as_values' => true,
150-
);
189+
));
151190

152191
.. image:: /images/reference/form/choice-example4.png
153192
:align: center
@@ -160,18 +199,24 @@ Field Options
160199
choices
161200
~~~~~~~
162201

163-
**type**: ``array`` **default**: ``array()``
202+
**type**: ``array`` or ``\Traversable`` **default**: ``array()``
164203

165204
This is the most basic way to specify the choices that should be used
166205
by this field. The ``choices`` option is an array, where the array key
167-
is the item's label and the array value is the item's value::
206+
is the choice's label and the array value is the choice's data::
168207

169208
$builder->add('inStock', 'choice', array(
170-
'choices' => array('In Stock' => true, 'Out of Stock' => false),
209+
'choices' => array(
210+
'In Stock' => true,
211+
'Out of Stock' => false,
212+
),
171213
// always include this
172214
'choices_as_values' => true,
173215
));
174216

217+
The component will try to cast the choices data to string to use it in view
218+
format, but you can customize it using the `choice_value`_ option.
219+
175220
.. include:: /reference/forms/types/options/choice_attr.rst.inc
176221

177222
.. _reference-form-choice-label:
@@ -229,9 +274,14 @@ choice_loader
229274

230275
**type**: :class:`Symfony\\Component\\Form\\ChoiceList\\Loader\\ChoiceLoaderInterface`
231276

232-
The ``choice_loader`` can be used to only partially load the choices in cases where
233-
a fully-loaded list is not necessary. This is only needed in advanced cases and
234-
would replace the ``choices`` option.
277+
The ``choice_loader`` can be used to load the choices form a data source with a
278+
custom logic (e.g query language) such as database or search engine.
279+
The list will be fully loaded to display the form, but while submission only the
280+
submitted choices will be loaded.
281+
282+
Also, the :class:``Symfony\\Component\\Form\\ChoiceList\\Factory\\ChoiceListFactoryInterface`` will cache the choice list
283+
so the same :class:``Symfony\\Component\\Form\\ChoiceList\\Loader\\ChoiceLoaderInterface`` can be used in different fields with more performance
284+
(reducing N queries to 1).
235285

236286
.. include:: /reference/forms/types/options/choice_name.rst.inc
237287

@@ -250,8 +300,8 @@ choices_as_values
250300

251301
The ``choices_as_values`` option was added to keep backward compatibility with the
252302
*old* way of handling the ``choices`` option. When set to ``false`` (or omitted),
253-
the choice keys are used as the underlying value and the choice values are shown
254-
to the user.
303+
the choice keys are used as the view value and the choice values are shown
304+
to the user as label.
255305

256306
* Before 2.7 (and deprecated now)::
257307

@@ -271,12 +321,11 @@ to the user.
271321
'choices_as_values' => true,
272322
));
273323

274-
In Symfony 3.0, the ``choices_as_values`` option doesn't exist, but the ``choice``
275-
type behaves as if it were set to true:
324+
As of Symfony 3.0, the ``choices_as_values`` option is ``true`` by default:
276325

277326
* Default for 3.0::
278327

279-
$builder->add('gender', 'choice', array(
328+
$builder->add('gender', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array(
280329
'choices' => array('Male' => 'm', 'Female' => 'f'),
281330
));
282331

‎reference/forms/types/options/choice_attr.rst.inc

Copy file name to clipboardExpand all lines: reference/forms/types/options/choice_attr.rst.inc
+20-8Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ choice_attr
44
.. versionadded:: 2.7
55
The ``choice_attr`` option was introduced in Symfony 2.7.
66

7-
**type**: ``array``, ``callable`` or ``string`` **default**: ``array()``
7+
**type**: ``array``, ``callable``, ``string`` or :class:``Symfony\\Component\\PropertyAccess\\PropertyPath`` **default**: ``array()``
88

9-
Use this to add additional HTML attributes to each choice. This can be an array
10-
of attributes (if they are the same for each choice), a callable or a property path
11-
(just like `choice_label`_).
9+
Use this to add additional HTML attributes to each choice. This can be used as
10+
a callable or a property path (just like `choice_label`_).
1211

13-
If an array, the keys of the ``choices`` array must be used as keys::
12+
Also, if used as an array, the keys of the ``choices`` array must be used as keys::
1413

1514
$builder->add('attending', 'choice', array(
1615
'choices' => array(
@@ -19,8 +18,21 @@ If an array, the keys of the ``choices`` array must be used as keys::
1918
'Maybe' => null,
2019
),
2120
'choices_as_values' => true,
22-
'choice_attr' => function($val, $key, $index) {
23-
// adds a class like attending_yes, attending_no, etc
24-
return ['class' => 'attending_'.strtolower($key)];
21+
'choice_attr' => array(
22+
// will be used for the second choice
23+
'No' => array('class' => 'singular_choice_option');
24+
),
25+
));
26+
27+
$builder->add('attending', 'choice', array(
28+
'choices' => array(
29+
'Yes' => true,
30+
'No' => false,
31+
'Maybe' => null,
32+
),
33+
'choices_as_values' => true,
34+
'choice_attr' => function() {
35+
// will be used for all choices
36+
return array('class' => 'choice_option');
2537
},
2638
));

‎reference/forms/types/options/choice_label.rst.inc

Copy file name to clipboardExpand all lines: reference/forms/types/options/choice_label.rst.inc
+33-21Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,29 @@ choice_label
44
.. versionadded:: 2.7
55
The ``choice_label`` option was introduced in Symfony 2.7.
66

7-
**type**: ``string``, ``callable`` or ``false`` **default**: ``null``
7+
**type**: ``string``, ``callable``, :class:``Symfony\\Component\\PropertyAccess\\PropertyPath`` or ``false`` **default**: ``null``
88

99
Normally, the array key of each item in the ``choices`` option is used as the
1010
text that's shown to the user. The ``choice_label`` option allows you to take
11-
more control::
11+
more control.
12+
13+
If your choice values are objects (default in ``EntityType``), then ``choice_label``
14+
can be a string :ref:`property path <reference-form-option-property-path>`. Imagine you have some
15+
``Status`` class with a ``getDisplayName()`` method::
16+
17+
$builder->add('attending', 'choice', array(
18+
'choices' => array(
19+
new Status(Status::YES),
20+
new Status(Status::NO),
21+
new Status(Status::MAYBE),
22+
),
23+
'choices_as_values' => true,
24+
'choice_label' => 'displayName',
25+
));
26+
27+
If set as a callable is called for each choice, passing you its model data ``$choice``
28+
and the ``$key`` from the choices array (default label). ``$value`` is either
29+
`choice_value`_ option value when defined or the default string value of the choice::
1230

1331
$builder->add('attending', 'choice', array(
1432
'choices' => array(
@@ -17,8 +35,8 @@ more control::
1735
'maybe' => null,
1836
),
1937
'choices_as_values' => true,
20-
'choice_label' => function ($value, $key, $index) {
21-
if ($value == true) {
38+
'choice_label' => function ($choice, $key, $value) {
39+
if (true === $choice) {
2240
return 'Definitely!';
2341
}
2442
return strtoupper($key);
@@ -28,26 +46,20 @@ more control::
2846
},
2947
));
3048

31-
This method is called for *each* choice, passing you the choice ``$value`` and the
32-
``$key`` from the choices array (``$index`` is related to `choice_value`_). This
33-
will give you:
49+
The example above would output:
3450

3551
.. image:: /images/reference/form/choice-example2.png
3652
:align: center
3753

38-
If your choice values are objects, then ``choice_label`` can also be a
39-
:ref:`property path <reference-form-option-property-path>`. Imagine you have some
40-
``Status`` class with a ``getDisplayName()`` method::
41-
42-
$builder->add('attending', 'choice', array(
43-
'choices' => array(
44-
new Status(Status::YES),
45-
new Status(Status::NO),
46-
new Status(Status::MAYBE),
47-
),
48-
'choices_as_values' => true,
49-
'choice_label' => 'displayName',
50-
));
51-
5254
If set to ``false``, all the tag labels will be discarded for radio or checkbox
5355
inputs. You can also return ``false`` from the callable to discard certain labels.
56+
57+
.. caution::
58+
59+
If you want to pass a string property path wich is also a callable (e.g 'range'),
60+
the component will treat it as a callable. You should pass a :class:``Symfony\\Component\\PropertyAccess\\PropertyPath``
61+
object to ensure the expected behavior::
62+
63+
use Symfony\Component\PropertyAccess\PropertyPath;
64+
65+
'choice_label' => new PropertyPath('range'),

‎reference/forms/types/options/choice_name.rst.inc

Copy file name to clipboardExpand all lines: reference/forms/types/options/choice_name.rst.inc
+8-6Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ choice_name
44
.. versionadded:: 2.7
55
The ``choice_name`` option was introduced in Symfony 2.7.
66

7-
**type**: ``callable`` or ``string`` **default**: ``null``
7+
**type**: ``callable``, ``string`` or :class:``Symfony\\Component\\PropertyAccess\\PropertyPath`` **default**: ``null``
88

9-
Controls the internal field name of the choice. You normally don't care about this,
10-
but in some advanced cases, you might. For example, this "name" becomes the index
11-
of the choice views in the template.
9+
Controls the internal field name of the choice. You normally don't care about
10+
this, but in some advanced cases, you might. For example, this "name" becomes
11+
the index of the choice views in the template.
1212
13-
This can be a callable or a property path. See `choice_label`_ for similar usage.
14-
If ``null`` is used, an incrementing integer is used as the name.
13+
This can be a callable or a property path. Both needs to return a non empty
14+
string, if ``null`` is used, an incrementing integer is used as the name.
15+
16+
See `choice_label`_ for similar usage.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.