@@ -70,10 +70,14 @@ 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+
76+ If the starting data for this field is ``true ``, then ``Yes `` will be auto-selected.
77+ In other words, each value of the ``choices `` option is the **choice ** data you
78+ want to deal with in PHP code, while the **key ** is the default label that will be
79+ shown to the user and the **value ** is the string that will be submitted to the
80+ form and used in the template for the corresponding html attribute.
7781
7882.. caution ::
7983
@@ -83,40 +87,98 @@ code, while the **key** is what will be shown to the user.
8387 and will be removed in 3.0. To read about the old API, read an older version of
8488 the docs.
8589
90+ .. note ::
91+
92+ Pre selected choices will depend on the **data ** passed to the field and
93+ the values of the ``choices `` option. However submitted choices will depend
94+ on the **string ** matching the **choice **. In the example above, the default
95+ values are incrementing integers because ``null `` cannot be casted to string.
96+ You should consider it as well when dealing with ``empty_data `` option::
97+
98+ $builder->add('isAttending', 'choice', array(
99+ 'choices' => array(
100+ 'Maybe' => null,
101+ 'Yes' => true,
102+ 'No' => false,
103+ ),
104+ 'choices_as_values' => true,
105+ 'data' => true, // pre selected choice
106+ 'empty_data' => '1', // default submitted value
107+ ));
108+
109+ When the ``multiple `` option is ``true `` the submitted data is an array of
110+ strings, you should the set the ``empty_value `` option accordingly.
111+ Also note that as a scalar ``false `` data as string **value ** is by default
112+ ``"0" `` to avoid conflict with placeholder value which is always an empty
113+ string.
114+
86115Advanced Example (with Objects!)
87116--------------------------------
88117
89118This field has a *lot * of options and most control how the field is displayed. In
90119this example, the underlying data is some ``Category `` object that has a ``getName() ``
91120method::
92121
93- $builder->add('category', 'choice', [
94- 'choices' => [
122+ $builder->add('category', 'choice', array(
123+ 'choices' => array(
95124 new Category('Cat1'),
96125 new Category('Cat2'),
97126 new Category('Cat3'),
98127 new Category('Cat4'),
99- ] ,
128+ ) ,
100129 'choices_as_values' => true,
101- 'choice_label' => function($category, $key, $index) {
102- /** @var Category $category */
130+ 'choice_label' => function(Category $category, $key, $value) {
103131 return strtoupper($category->getName());
104132 },
105- 'choice_attr' => function($category, $key, $index ) {
106- return [ 'class' => 'category_'.strtolower($category->getName())] ;
133+ 'choice_attr' => function(Category $category, $key, $value ) {
134+ return array( 'class' => 'category_'.strtolower($category->getName())) ;
107135 },
108- 'group_by' => function($category, $key, $index ) {
136+ 'group_by' => function(Category $category, $key, $value ) {
109137 // randomly assign things into 2 groups
110138 return rand(0, 1) == 1 ? 'Group A' : 'Group B';
111139 },
112- 'preferred_choices' => function($category, $key, $index ) {
113- return $category->getName() == 'Cat2' || $category->getName() == 'Cat3' ;
140+ 'preferred_choices' => function(Category $category, $key, $value ) {
141+ return 'Cat2' === $category->getName() || 'Cat3' === $category->getName();
114142 },
115- ] );
143+ ) );
116144
117145You can also customize the `choice_name `_ and `choice_value `_ of each choice if
118146you need further HTML customization.
119147
148+ .. caution ::
149+
150+ When dealing with objects as choices, you should be careful about how
151+ string values are set to use them with the `empty_data ` option.
152+ In the example above, the default values are incrementing integers if the
153+ ``Category `` class does not implement ``toString `` method.
154+ To get a full control of the string values use the `choice_value `_ option::
155+
156+ $builder->add('category', 'choice', array(
157+ 'choices' => array(
158+ new Category('Cat1'),
159+ new Category('Cat2'),
160+ new Category('Cat3'),
161+ new Category('Cat4'),
162+ ),
163+ 'choices_as_values' => true,
164+ 'choice_value' => function(Category $category = null) {
165+ if (null === $category) {
166+ return '';
167+ }
168+
169+ return strtolower($category->getName());
170+ },
171+ 'choice_label' => function(Category $category, $key, $value) {
172+ return strtoupper($category->getName());
173+ },
174+ 'multiple' => true,
175+ 'empty_data' => array('cat2'), // default submitted value
176+ // an array because of multiple option
177+ ));
178+
179+ Note that `choice_value `_ option set as a callable can get passed ``null ``
180+ when no data is preset or submitted.
181+
120182.. _forms-reference-choice-tags :
121183
122184.. include :: /reference/forms/types/options/select_how_rendered.rst.inc
@@ -135,19 +197,19 @@ Grouping Options
135197
136198You can easily "group" options in a select by passing a multi-dimensional choices array::
137199
138- $builder->add('stockStatus', 'choice', [
139- 'choices' => [
140- 'Main Statuses' => [
200+ $builder->add('stockStatus', 'choice', array(
201+ 'choices' => array(
202+ 'Main Statuses' => array(
141203 'Yes' => 'stock_yes',
142204 'No' => 'stock_no',
143- ] ,
144- 'Out of Stock Statuses' => [
205+ ) ,
206+ 'Out of Stock Statuses' => array(
145207 'Backordered' => 'stock_backordered',
146208 'Discontinued' => 'stock_discontinued',
147- ]
148- ] ,
209+ ),
210+ ) ,
149211 'choices_as_values' => true,
150- );
212+ )) ;
151213
152214.. image :: /images/reference/form/choice-example4.png
153215 :align: center
@@ -160,18 +222,25 @@ Field Options
160222choices
161223~~~~~~~
162224
163- **type **: ``array `` **default **: ``array() ``
225+ **type **: ``array `` or `` \Traversable `` **default **: ``array() ``
164226
165227This is the most basic way to specify the choices that should be used
166228by 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 ::
229+ is the choice 's label and the array value is the choice 's data ::
168230
169231 $builder->add('inStock', 'choice', array(
170- 'choices' => array('In Stock' => true, 'Out of Stock' => false),
232+ 'choices' => array(
233+ 'In Stock' => true,
234+ 'Out of Stock' => false,
235+ ),
171236 // always include this
172237 'choices_as_values' => true,
173238 ));
174239
240+ The component will try to cast the choices data to string to use it in view
241+ format, in that case ``"0" `` and ``"1" ``, but you can customize it using the
242+ `choice_value `_ option.
243+
175244.. include :: /reference/forms/types/options/choice_attr.rst.inc
176245
177246.. _reference-form-choice-label :
@@ -229,9 +298,14 @@ choice_loader
229298
230299**type **: :class: `Symfony\\ Component\\ Form\\ ChoiceList\\ Loader\\ ChoiceLoaderInterface `
231300
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.
301+ The ``choice_loader `` can be used to load the choices form a data source with a
302+ custom logic (e.g query language) such as database or search engine.
303+ The list will be fully loaded to display the form, but while submission only the
304+ submitted choices will be loaded.
305+
306+ Also, the :class: ``Symfony\\ Component\\ Form\\ ChoiceList\\ Factory\\ ChoiceListFactoryInterface` ` will cache the choice list
307+ so the same :class: ``Symfony\\ Component\\ Form\\ ChoiceList\\ Loader\\ ChoiceLoaderInterface` ` can be used in different fields with more performance
308+ (reducing N queries to 1).
235309
236310.. include :: /reference/forms/types/options/choice_name.rst.inc
237311
@@ -250,34 +324,33 @@ choices_as_values
250324
251325The ``choices_as_values `` option was added to keep backward compatibility with the
252326*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.
327+ the choice keys are used as the view value and the choice values are shown
328+ to the user as label .
255329
256330* Before 2.7 (and deprecated now)::
257331
258- $builder->add('gender ', 'choice', array(
259- // Shows "Male " to the user, returns "m " when selected
260- 'choices' => array('m ' => 'Male ', 'f ' => 'Female '),
332+ $builder->add('agree ', 'choice', array(
333+ // Shows "Yes " to the user, returns "1 " when selected
334+ 'choices' => array('1 ' => 'Yes ', '0 ' => 'No '),
261335 // before 2.7, this option didn't actually exist, but the
262336 // behavior was equivalent to setting this to false in 2.7.
263337 'choices_as_values' => false,
264338 ));
265339
266340* Since 2.7::
267341
268- $builder->add('gender ', 'choice', array(
269- // Shows "Male " to the user, returns "m " when selected
270- 'choices' => array('Male ' => 'm ', 'Female ' => 'f '),
342+ $builder->add('agree ', 'choice', array(
343+ // Shows "Yes " to the user, returns "1 " when selected
344+ 'choices' => array('Yes ' => '1 ', 'No ' => '0 '),
271345 'choices_as_values' => true,
272346 ));
273347
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:
348+ As of Symfony 3.0, the ``choices_as_values `` option is ``true `` by default:
276349
277350* Default for 3.0::
278351
279- $builder->add('gender ', 'choice ', array(
280- 'choices' => array('Male ' => 'm ', 'Female ' => 'f '),
352+ $builder->add('agree ', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType ', array(
353+ 'choices' => array('Yes ' => '1 ', 'No ' => '0 '),
281354 ));
282355
283356.. include :: /reference/forms/types/options/expanded.rst.inc
0 commit comments