Skip to content

[Form] add choice_filter option to ChoiceType #18334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

HeahDude
Copy link
Contributor

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #11847, #14072
License MIT
Doc PR todo
  • Add some tests
  • Add more tests in ChoiceTypeTest
  • Address a doc PR
  • Update the CHANGELOG
  • Add a note in the UPGRADE file

@HeahDude
Copy link
Contributor Author

Basic usage:

$builder->add('locales', LocaleType::class, array(
    'choice_filter' => function ($choice) use ($userLocales) {
        return in_array($choice, $userLocales, true);
    },
));

$builder->add('entities', EntityType::class, array(
    'class' => \AppBundle\Entity\Issue::class,
    'choice_filter' => function ($choice) use ($user) {
        return $user->canHandle($choice);
    },
));

@HeahDude HeahDude force-pushed the feature-choice_type-choice_filter-option branch 5 times, most recently from fac72f6 to 476eb3e Compare March 28, 2016 15:08
@HeahDude
Copy link
Contributor Author

Tests added.

@HeahDude
Copy link
Contributor Author

This is a full BC implementation.

The only thing that should be noted in UPGRADE is that someone uses its own ChoiceListFactory should either implement FilteredChoiceListFactoryInterface or use the FilteringFactoryDecorator to use the new choice_filter option, otherwise it will simply be ignored.

{
// Don't hash the filter since the original choices may have been loaded already
// with a different filter if any.
$hash = CachingFactoryDecorator::generateHash(array($loader, $value));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just not sure about the over caching here, but it seems that considering this decorator might not decorate the CachingFactoryDecorator, keeping the resolved choices to filter should be the right thing to do.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This caching is useless, as the decorated choice list already has caching

@HeahDude HeahDude force-pushed the feature-choice_type-choice_filter-option branch from 476eb3e to bd476e1 Compare March 28, 2016 15:55
@HeahDude
Copy link
Contributor Author

@stof any thought on this one regarding the previous (wrong) implementation ?

@HeahDude
Copy link
Contributor Author

ping @webmozart :)

/**
* @dataProvider provideChoicesAndFilter
*/
public function testCreateFilteredChoiceListFromLoaderLoadsOriginalListOnFirstCall($choices, $choiceList, $filter, $filteredChoices)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof
Copy link
Member

stof commented Apr 7, 2016

@HeahDude this will have to wait until 3.2. We are already in the 3.1 feature freeze, and there is still too much to evaluate about this feature to merge it now (we are not yet fully freezed as we allow us to include some PRs which are ready but not yet merged, but this feature cannot be considered as ready yet IMO).
So I will focus on the review of other PRs for now (the ones still considered for inclusion in 3.1) and come back at this feature later.

@HeahDude
Copy link
Contributor Author

HeahDude commented Apr 7, 2016

@stof I absolutely agree ;) Thank you for your feedback!

Status: Needs Work

@HeahDude HeahDude changed the title [Form] add choice_filter option to ChoiceType [WIP] [3.2] [Form] add choice_filter option to ChoiceType Apr 28, 2016
@nicolas-grekas nicolas-grekas changed the title [WIP] [3.2] [Form] add choice_filter option to ChoiceType [Form] add choice_filter option to ChoiceType Dec 6, 2016
@nicolas-grekas nicolas-grekas added this to the 3.x milestone Dec 6, 2016
@ogizanagi
Copy link
Contributor

@HeahDude : What about accepting an array in the choice_filter option?

The following:

$builder->add('locales', LocaleType::class, array(
    'choice_filter' => $userLocales,
));

will automatically generate the callable using in_array.
It'll help when the type is configurable from a configuration file for instance (like in EasyAdminBundle).

@HeahDude
Copy link
Contributor Author

will automatically generate the callable using in_array.

I like the idea, thanks! I'll try to implement it soon when revisiting this one.

@HeahDude
Copy link
Contributor Author

@ogizanagi Just curious why not simply use the choices option of the ChoiceType in this case?

@ogizanagi
Copy link
Contributor

ogizanagi commented Dec 11, 2016

I expected this question 😅

This allows to blindly filter the available values, without caring of the implementation of the type. In a config file, you only want to use %locales% for instance (which only contains values).
Behind, the type has the responsibility to associate the proper labels for instance.

Using the choices option of the ChoiceType forces you to redefine everything.

@HeahDude
Copy link
Contributor Author

HeahDude commented Dec 11, 2016

I think you can already solve this case using a custom type:

class UserLocaleType extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver
            ->setRequired('display_locale')
            ->setNormalizer('choice_label', function (Options $options) {
                $displayLocale = $options['display_locale'];

                return function ($choice) use ($displayLocale) {
                    return Intl::getLocaleBundle()->getLocaleName($choice, $displayLocale);
                };
            })
        ;
    }

    public function getParent()
    {
        return ChoiceType::class;
    }
}

// Then you can do
$builder->add('locales', UserLocaleType::class, array(
    'choices' => $userLocales,
    'display_locale' => $userLocale,
));

But I agree, the filter option definitely simplifies the implementation though :)

@HeahDude
Copy link
Contributor Author

But regarding performances implementing a specific type like in my example may be better.

@ogizanagi
Copy link
Contributor

ogizanagi commented Dec 11, 2016

I agree. Such uses of the choice_filter option will be reserved mainly for countries, locales, languages (...). I doubt it'll have a big impact on performances, but it has a very good one on DX.

@xabbuh
Copy link
Member

xabbuh commented Dec 18, 2016

Is this really something that will be commonly used? I mean if you need to filter your choices, why don't you just do that when specifying the choices option then?

@HeahDude
Copy link
Contributor Author

@xabbuh in case of inheritance there would be no need to define again the choices and we could use the same cached choice list on which to apply the filter.

For the EntityType it would allow to filter choices thanks to dynamic properties or method that could not be used with a custom query builder.

So to me this feature is the right answer to both needs.

@xabbuh
Copy link
Member

xabbuh commented Dec 30, 2016

@HeahDude Sounds reasonable to me. Do you think you can finish this one?

@nicolas-grekas
Copy link
Member

ping @HeahDude

@nicolas-grekas nicolas-grekas modified the milestones: 3.4, 4.1 Oct 8, 2017
@fabpot
Copy link
Member

fabpot commented Jan 24, 2018

@HeahDude Do you think you can work on finishing this PR or shall we close it?

@fabpot
Copy link
Member

fabpot commented Mar 31, 2018

Closing this PR as there is no more activity. @HeahDude Feel free to reopen whenever you have time to finish it. Thanks.

@yceruto
Copy link
Member

yceruto commented Sep 26, 2018

See alternative #28607

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants