From 8b0c09ef9c1bd28ab27bda24128f6a31f04e3062 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Sat, 22 Feb 2020 18:25:30 +0100 Subject: [PATCH] [Form] added the "choice_filter" option --- reference/forms/types/choice.rst | 3 + .../forms/types/options/choice_filter.rst.inc | 82 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 reference/forms/types/options/choice_filter.rst.inc diff --git a/reference/forms/types/choice.rst b/reference/forms/types/choice.rst index 98fab9bf9b0..fb1df969b9d 100644 --- a/reference/forms/types/choice.rst +++ b/reference/forms/types/choice.rst @@ -14,6 +14,7 @@ To use this field, you must specify *either* ``choices`` or ``choice_loader`` op +-------------+------------------------------------------------------------------------------+ | Options | - `choices`_ | | | - `choice_attr`_ | +| | - `choice_filter`_ | | | - `choice_label`_ | | | - `choice_loader`_ | | | - `choice_name`_ | @@ -212,6 +213,8 @@ correct types will be assigned to the model. .. include:: /reference/forms/types/options/choice_attr.rst.inc +.. include:: /reference/forms/types/options/choice_filter.rst.inc + .. _reference-form-choice-label: .. include:: /reference/forms/types/options/choice_label.rst.inc diff --git a/reference/forms/types/options/choice_filter.rst.inc b/reference/forms/types/options/choice_filter.rst.inc new file mode 100644 index 00000000000..1f320bf1a69 --- /dev/null +++ b/reference/forms/types/options/choice_filter.rst.inc @@ -0,0 +1,82 @@ +``choice_filter`` +~~~~~~~~~~~~~~~~~ + +**type**: ``callable``, ``string`` or :class:`Symfony\\Component\\PropertyAccess\\PropertyPath` **default**: ``null`` + +.. versionadded:: 5.1 + + The ``choice_filter`` option has been introduced in Symfony 5.1. + +When using predefined choice types from Symfony core or vendor libraries (i.e. +:doc:`CountryType `) this option lets you +define a callable that take each choice as only argument and must return +``true`` to keep it or ``false`` to discard it:: + + // src/Form/Type/AddressType.php + namespace App\Form\Type; + + use Symfony\Component\Form\AbstractType; + use Symfony\Component\Form\Extension\Core\Type\CountryType; + use Symfony\Component\Form\FormBuilderInterface; + use Symfony\Component\OptionsResolver\OptionsResolver; + + class AddressType extends AbstractType + { + public function configureOptions(OptionsResolver $resolver) + { + $resolver + ->setDefaults([ + // enable this type to accept a limited set of countries + 'allowed_countries' => null, + ]) + ; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $allowedCountries = $options['allowed_countries']; + + $builder + // ... + ->add('country', CountryType::class, [ + // if the AddressType "allowed_countries" option is passed, + // use it to create a filter + 'choice_filter' => $allowedCountries ? function ($countryCode) use ($allowedCountries) { + return in_array($countryCode, $allowedCountries, true); + } : null, + + ]) + ; + } + +The option can be a callable or a property path when choices are objects:: + + // ... + $builder + ->add('category', ChoiceType::class, [ + // ... + 'choice_filter' => 'isSelectable', + ]) + ; + +.. tip:: + + Considering this ``AddressType`` could be an entry of a ``CollectionType`` + you should use the :class:`Symfony\\Component\\Form\\ChoiceList\\ChoiceList` + class helper to enable caching:: + + // src/Form/Type/AddressType.php + // ... + use Symfony\Component\Form\ChoiceList\ChoiceList; + + // ... + 'choice_filter' => $allowedCountries ? ChoiceList::filter( + // pass the type as first argument + $this, + function ($countryCode) use ($allowedCountries) { + return in_array($countryCode, $allowedCountries, true); + }, + // pass the option that makes the filter "vary" to compute a unique hash + $allowedCountries + ) : null, + // ...