Skip to content

Commit

Permalink
[Form] minor fixes in ChoiceType options
Browse files Browse the repository at this point in the history
  • Loading branch information
HeahDude authored and OskarStark committed Feb 18, 2020
1 parent 3ba2ad8 commit 4ee4102
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 38 deletions.
46 changes: 33 additions & 13 deletions reference/forms/types/choice.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ This will create a ``select`` drop-down like this:

If the user selects ``No``, the form will return ``false`` for this field. Similarly,
if the starting data for this field is ``true``, then ``Yes`` will be auto-selected.
In other words, the **value** of each item is the value you want to get/set in PHP
code, while the **key** is what will be shown to the user.
In other words, the **choice** of each item is the value you want to get/set in PHP
code, while the **key** is the **label** that will be shown to the user.

Advanced Example (with Objects!)
--------------------------------
Expand All @@ -95,23 +95,40 @@ method::
new Category('Cat3'),
new Category('Cat4'),
],
'choice_label' => function(Category $category, $key, $value) {
return strtoupper($category->getName());
// "name" is a property path, meaning Symfony will look for a public
// property or a public method like "getName()" to define the input
// string value that will be submitted by the form
'choice_value' => 'name',
// a callback to return the label for a given choice
// if a placeholder is used, its empty value (null) may be passed but
// its label is defined by its own "placeholder" option
'choice_label' => function(?Category $category) {
return $category ? strtoupper($category->getName()) : '';
},
'choice_attr' => function(Category $category, $key, $value) {
return ['class' => 'category_'.strtolower($category->getName())];
// returns the html attributes for each option input (may be radio/checkbox)
'choice_attr' => function(?Category $category) {
return $category ? ['class' => 'category_'.strtolower($category->getName())] : [];
},
'group_by' => function(Category $category, $key, $value) {
// every option can use a string property path or any callable that get
// passed each choice as argument, but it may not be needed
'group_by' => function() {
// randomly assign things into 2 groups
return rand(0, 1) == 1 ? 'Group A' : 'Group B';
},
'preferred_choices' => function(Category $category, $key, $value) {
return $category->getName() == 'Cat2' || $category->getName() == 'Cat3';
// a callback to return whether a category is preferred
'preferred_choices' => function(?Category $category) {
return $category && 100 < $category->getArticleCounts();
},
]);

You can also customize the `choice_name`_ and `choice_value`_ of each choice if
you need further HTML customization.
You can also customize the `choice_name`_ of each choice. You can learn more
about all of these options in the sections below.

.. caution::

The *placeholder* is a specific field, when the choices are optional the
first item in the list must be empty, so the user can unselect.
Be sure to always handle the empty choice ``null`` when using callbacks.

.. _forms-reference-choice-tags:

Expand Down Expand Up @@ -151,7 +168,7 @@ by passing a multi-dimensional ``choices`` array::
.. image:: /_images/reference/form/choice-example4.png
:align: center

To get fancier, use the `group_by`_ option.
To get fancier, use the `group_by`_ option instead.

Field Options
-------------
Expand All @@ -169,7 +186,10 @@ is the item's label and the array value is the item's value::
// ...

$builder->add('inStock', ChoiceType::class, [
'choices' => ['In Stock' => true, 'Out of Stock' => false],
'choices' => [
'In Stock' => true,
'Out of Stock' => false,
],
]);

If there are choice values that are not scalar or the stringified
Expand Down
2 changes: 1 addition & 1 deletion reference/forms/types/options/choice_attr.rst.inc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
``choice_attr``
~~~~~~~~~~~~~~~

**type**: ``array``, ``callable`` or ``string`` **default**: ``[]``
**type**: ``array``, ``callable``, ``string`` or :class:`Symfony\\Component\\PropertyAccess\\PropertyPath` **default**: ``[]``

Use this to add additional HTML attributes to each choice. This can be
an associative array where the keys match the choice keys and the values
Expand Down
4 changes: 2 additions & 2 deletions reference/forms/types/options/choice_label.rst.inc
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
``choice_label``
~~~~~~~~~~~~~~~~

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

Normally, the array key of each item in the ``choices`` option is used as the
By default, the array key of each item in the ``choices`` option is used as the
text that's shown to the user. The ``choice_label`` option allows you to take
more control::

Expand Down
7 changes: 4 additions & 3 deletions reference/forms/types/options/choice_name.rst.inc
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
``choice_name``
~~~~~~~~~~~~~~~

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

Controls the internal field name of the choice. You normally don't care about this,
but in some advanced cases, you might. For example, this "name" becomes the index
of the choice views in the template.
of the choice views in the template and is used as part o the field name
attribute.
This can be a callable or a property path. See `choice_label`_ for similar usage.
If ``null`` is used, an incrementing integer is used as the name.
By default, the choice key or an incrementing integer may be used (starting at ``0``).
.. caution::
Expand Down
18 changes: 5 additions & 13 deletions reference/forms/types/options/choice_value.rst.inc
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
``choice_value``
~~~~~~~~~~~~~~~~

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

Returns the string "value" for each choice, which must be unique across all choices.
This is used in the ``value`` attribute in HTML and submitted in the POST/PUT requests.
You don't normally need to worry about this, but it might be handy when processing
an API request (since you can configure the value that will be sent in the API request).
This can be a callable or a property path. If ``null`` is given, an incrementing
integer is used as the value.
This can be a callable or a property path. By default, the choices are used if they
can be casted to strings. Otherwise an incrementing integer is used (starting at ``0``).
If you pass a callable, it will receive one argument: the choice itself. When using
the :doc:`/reference/forms/types/entity`, the argument will be the entity object
for each choice or ``null`` in some cases, which you need to handle::
for each choice or ``null`` in a placeholder is used, which you need to handle::
'choice_value' => function (MyOptionEntity $entity = null) {
'choice_value' => function (?MyOptionEntity $entity) {
return $entity ? $entity->getId() : '';
},
.. caution::
In Symfony 2.7, there was a small backwards-compatibility break with how the
``value`` attribute of options is generated. This is not a problem unless you
rely on the option values in JavaScript. See `issue #14825`_ for details.
.. _`issue #14825`: https://github.com/symfony/symfony/pull/14825
6 changes: 3 additions & 3 deletions reference/forms/types/options/group_by.rst.inc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
``group_by``
~~~~~~~~~~~~

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

You can group the ``<option>`` elements of a ``<select>`` into ``<optgroup>``
by passing a multi-dimensional array to ``choices``. See the
Expand All @@ -25,9 +25,9 @@ Take the following example::
'group_by' => function($choice, $key, $value) {
if ($choice <= new \DateTime('+3 days')) {
return 'Soon';
} else {
return 'Later';
}

return 'Later';
},
]);

Expand Down
6 changes: 3 additions & 3 deletions reference/forms/types/options/preferred_choices.rst.inc
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
``preferred_choices``
~~~~~~~~~~~~~~~~~~~~~

**type**: ``array``, ``callable`` or ``string`` **default**: ``[]``
**type**: ``array``, ``callable``, ``string`` or :class:`Symfony\\Component\\PropertyAccess\\PropertyPath` **default**: ``[]``

This option allows you to move certain choices to the top of your list with a visual
separator between them and the rest of the options. If you have a form of languages,
you can list the most popular on top, like Bork Bork and Pirate::
you can list the most popular on top, like Bork and Pirate::

use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
// ...
Expand All @@ -14,7 +14,7 @@ you can list the most popular on top, like Bork Bork and Pirate::
'choices' => [
'English' => 'en',
'Spanish' => 'es',
'Bork' => 'muppets',
'Bork' => 'muppets',
'Pirate' => 'arr',
],
'preferred_choices' => ['muppets', 'arr'],
Expand Down

0 comments on commit 4ee4102

Please sign in to comment.