Skip to content

Commit 9fc18e7

Browse files
HeahDudejaviereguiluz
authored andcommitted
[Form] added the new ChoiceList class to configure ChoiceType options
1 parent 0045470 commit 9fc18e7

8 files changed

+170
-25
lines changed

reference/forms/types/choice.rst

+7-24
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ To get fancier, use the `group_by`_ option instead.
181181
Field Options
182182
-------------
183183

184+
.. versionadded:: 5.1
185+
186+
The :class:`Symfony\\Component\\Form\\ChoiceList\\ChoiceList` class has
187+
been introduced in Symfony 5.1, to help configuring choices options.
188+
184189
choices
185190
~~~~~~~
186191

@@ -211,31 +216,9 @@ correct types will be assigned to the model.
211216

212217
.. include:: /reference/forms/types/options/choice_label.rst.inc
213218

214-
choice_loader
215-
~~~~~~~~~~~~~
216-
217-
**type**: :class:`Symfony\\Component\\Form\\ChoiceList\\Loader\\ChoiceLoaderInterface`
218-
219-
The ``choice_loader`` can be used to only partially load the choices in cases where
220-
a fully-loaded list is not necessary. This is only needed in advanced cases and
221-
would replace the ``choices`` option.
222-
223-
You can use an instance of :class:`Symfony\\Component\\Form\\ChoiceList\\Loader\\CallbackChoiceLoader`
224-
if you want to take advantage of lazy loading::
225-
226-
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
227-
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
228-
// ...
229-
230-
$builder->add('constants', ChoiceType::class, [
231-
'choice_loader' => new CallbackChoiceLoader(function() {
232-
return StaticClass::getConstants();
233-
}),
234-
]);
219+
.. _reference-form-choice-loader:
235220

236-
This will cause the call of ``StaticClass::getConstants()`` to not happen if the
237-
request is redirected and if there is no pre set or submitted data. Otherwise
238-
the choice options would need to be resolved thus triggering the callback.
221+
.. include:: /reference/forms/types/options/choice_loader.rst.inc
239222

240223
.. include:: /reference/forms/types/options/choice_name.rst.inc
241224

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

+17
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,20 @@ If an array, the keys of the ``choices`` array must be used as keys::
2424
return ['class' => 'attending_'.strtolower($key)];
2525
},
2626
]);
27+
28+
.. tip::
29+
30+
When defining a custom type, you should use the
31+
:class:`Symfony\\Component\\Form\\ChoiceList\\ChoiceList` class helper::
32+
33+
use App\Entity\Category;
34+
use Symfony\Component\Form\ChoiceList\ChoiceList;
35+
36+
// ...
37+
$builder->add('choices', ChoiceType::class, [
38+
'choice_label' => ChoiceList::attr($this, function (?Category $category) {
39+
return $category ? ['data-uuid' => $category->getUuid()] : [];
40+
}),
41+
]);
42+
43+
See the :ref:`"choice_loader" option documentation <reference-form-choice-loader>`.

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

+14
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,17 @@ If your choice values are objects, then ``choice_label`` can also be a
5353

5454
If set to ``false``, all the tag labels will be discarded for radio or checkbox
5555
inputs. You can also return ``false`` from the callable to discard certain labels.
56+
57+
.. tip::
58+
59+
When defining a custom type, you should use the
60+
:class:`Symfony\\Component\\Form\\ChoiceList\\ChoiceList` class helper::
61+
62+
use Symfony\Component\Form\ChoiceList\ChoiceList;
63+
64+
// ...
65+
$builder->add('choices', ChoiceType::class, [
66+
'choice_label' => ChoiceList::label($this, 'displayName'),
67+
]);
68+
69+
See the :ref:`"choice_loader" option documentation <reference-form-choice-loader>`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
choice_loader
2+
~~~~~~~~~~~~~
3+
4+
**type**: :class:`Symfony\\Component\\Form\\ChoiceList\\Loader\\ChoiceLoaderInterface`
5+
6+
The ``choice_loader`` can be used instead of ``choices`` option. It allows to
7+
create a list lazily or partially when fetching only the choices for a set of
8+
submitted values (i.e. querying a search engine like ``ElasticSearch`` can be
9+
a heavy process).
10+
11+
You can use an instance of :class:`Symfony\\Component\\Form\\ChoiceList\\Loader\\CallbackChoiceLoader`
12+
if you want to take advantage of lazy loading::
13+
14+
use App\StaticClass;
15+
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
16+
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
17+
// ...
18+
19+
$builder->add('loaded_choices', ChoiceType::class, [
20+
'choice_loader' => new CallbackChoiceLoader(function() {
21+
return StaticClass::getConstants();
22+
}),
23+
]);
24+
25+
This will cause the call of ``StaticClass::getConstants()`` to not happen if the
26+
request is redirected and if there is no pre set or submitted data. Otherwise
27+
the choice options would need to be resolved thus triggering the callback.
28+
29+
When you're defining a custom choice type that may be reused in many fields
30+
(like entries of a collection) or reused in multiple forms at once, you
31+
should use the :class:`Symfony\\Component\\Form\\ChoiceList\\ChoiceList`
32+
static methods to wrap the loader and make the choice list cacheable for
33+
better performance::
34+
35+
use App\Form\ChoiceList\CustomChoiceLoader;
36+
use App\StaticClass;
37+
use Symfony\Component\Form\AbstractType;
38+
use Symfony\Component\Form\ChoiceList\ChoiceList;
39+
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
40+
use Symfony\Component\OptionsResolver\Options;
41+
use Symfony\Component\OptionsResolver\OptionsResolver;
42+
43+
class ConstantsType extends AbstractType
44+
{
45+
public static function getExtendedTypes(): iterable
46+
{
47+
return [ChoiceType::class];
48+
}
49+
50+
public function configureOptions(OptionsResolver $resolver)
51+
{
52+
$resolver->setDefaults([
53+
// the example below will create a CallbackChoiceLoader from the callable
54+
'choice_loader' => ChoiceList::lazy($this, function() {
55+
return StaticClass::getConstants();
56+
}),
57+
58+
// you can pass your own loader as well, depending on other options
59+
'some_key' => null,
60+
'choice_loader' => function (Options $options) {
61+
return ChoiceList::loader(
62+
// pass the instance of the type or type extension which is
63+
// currently configuring the choice list as first argument
64+
$this,
65+
// pass the other option to the loader
66+
new CustomChoiceLoader($options['some_key']),
67+
// ensure the type stores a loader per key
68+
// by using the special third argument "$vary"
69+
// an array containing anything that "changes" the loader
70+
[$options['some_key']]
71+
);
72+
},
73+
]);
74+
}
75+
}

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

+15-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,26 @@
55

66
Controls the internal field name of the choice. You normally don't care about this,
77
but in some advanced cases, you might. For example, this "name" becomes the index
8-
of the choice views in the template and is used as part o the field name
8+
of the choice views in the template and is used as part of the field name
99
attribute.
1010

1111
This can be a callable or a property path. See `choice_label`_ for similar usage.
1212
By default, the choice key or an incrementing integer may be used (starting at ``0``).
1313

14+
.. tip::
15+
16+
When defining a custom type, you should use the
17+
:class:`Symfony\\Component\\Form\\ChoiceList\\ChoiceList` class helper::
18+
19+
use Symfony\Component\Form\ChoiceList\ChoiceList;
20+
21+
// ...
22+
$builder->add('choices', ChoiceType::class, [
23+
'choice_name' => ChoiceList::fieldName($this, 'name'),
24+
]);
25+
26+
See the :ref:`"choice_loader" option documentation <reference-form-choice-loader>`.
27+
1428
.. caution::
1529

1630
The configured value must be a valid form name. Make sure to only return

reference/forms/types/options/choice_value.rst.inc

+14
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,17 @@ for each choice or ``null`` in a placeholder is used, which you need to handle::
1818
'choice_value' => function (?MyOptionEntity $entity) {
1919
return $entity ? $entity->getId() : '';
2020
},
21+
22+
.. tip::
23+
24+
When defining a custom type, you should use the
25+
:class:`Symfony\\Component\\Form\\ChoiceList\\ChoiceList` class helper::
26+
27+
use Symfony\Component\Form\ChoiceList\ChoiceList;
28+
29+
// ...
30+
$builder->add('choices', ChoiceType::class, [
31+
'choice_value' => ChoiceList::value($this, 'uuid'),
32+
]);
33+
34+
See the :ref:`"choice_loader" option documentation <reference-form-choice-loader>`.

reference/forms/types/options/group_by.rst.inc

+14
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,17 @@ a "Later" ``<optgroup>``:
4040
If you return ``null``, the option won't be grouped. You can also pass a string
4141
"property path" that will be called to get the group. See the `choice_label`_ for
4242
details about using a property path.
43+
44+
.. tip::
45+
46+
When defining a custom type, you should use the
47+
:class:`Symfony\\Component\\Form\\ChoiceList\\ChoiceList` class helper::
48+
49+
use Symfony\Component\Form\ChoiceList\ChoiceList;
50+
51+
// ...
52+
$builder->add('choices', ChoiceType::class, [
53+
'group_by' => ChoiceList::groupBy($this, 'category'),
54+
]);
55+
56+
See the :ref:`"choice_loader" option documentation <reference-form-choice-loader>`.

reference/forms/types/options/preferred_choices.rst.inc

+14
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,17 @@ when rendering the field:
6363
<?= $view['form']->widget($form['publishAt'], [
6464
'separator' => '=====',
6565
]) ?>
66+
67+
.. tip::
68+
69+
When defining a custom type, you should use the
70+
:class:`Symfony\\Component\\Form\\ChoiceList\\ChoiceList` class helper::
71+
72+
use Symfony\Component\Form\ChoiceList\ChoiceList;
73+
74+
// ...
75+
$builder->add('choices', ChoiceType::class, [
76+
'preferred_choices' => ChoiceList::preferred($this, 'taggedAsFavorite'),
77+
]);
78+
79+
See the :ref:`"choice_loader" option documentation <reference-form-choice-loader>`.

0 commit comments

Comments
 (0)