Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork5.3k
Description
Currently, the ChoiceType documentation is IMO not clearly worded. I know that readability is important, but since this type is quite flexible and complex, being precise is even more important. All code examples and descriptions should be updated to use the following terms:
- choice: The model value of the
choicesarray. E.g.:true,false,object (Category), ... - key: The key of the
choicesarray. - value: The HTML value. The value is always a string. E.g.:
'0','1','yes','no', ... Values must be free of duplicates, since they are used to identify the corresponding choice when submitting the form.
This naming is important since those values are passed from one callable to another:
- The
choice_valuecallable with signaturefunction ($choice)receives thechoice and returns the stringvalue. - The
choice_labelcallable with signaturefunction ($choice, $key, $value)receives thechoice, thekey and thevalue and returns a string label. The default value isfunction ($choice, $key, $value) => $key, i.e. the key of thechoicesarray is used as label by default. - The
choice_namecallable has the same signature aschoice_labeland outputs the form name used for checkboxes/radio buttons. - The
choice_attrcallable has the same signature aschoice_labeland outputs the HTML attributes.
Furthermore, thechoice_loader is not completely accurate:
The choice_loader can be used to only partially load the choices in cases where a fully-loaded list is not necessary. This is only needed in advanced cases and would replace the choices option.
I would rephrase this. The choice loader is used to load choices from a data source that can be queried with a query language, such as a database or a search engine. When the choice field is displayed, the full list is loaded, but when it is submitted, only the submitted value is looked up. A second benefit is that different fields that use the sameChoiceLoader instance use the same cached choice list, reducing N queries to 1.
Before/After code examples:
Before:
useSymfony\Component\Form\Extension\Core\Type\ChoiceType;// ...$builder->add('attending', ChoiceType::class,array('choices' =>array('yes' =>true,'no' =>false,'maybe' =>null, ),'choices_as_values' =>true,'choice_label' =>function ($value,$key,$index) {if ($value ==true) {return'Definitely!'; }returnstrtoupper($key);// or if you want to translate some key//return 'form.choice.'.$key; },));
After:
useSymfony\Component\Form\Extension\Core\Type\ChoiceType;// ...$builder->add('attending', ChoiceType::class,array('choices' =>array('yes' =>true,'no' =>false,'maybe' =>null, ),'choices_as_values' =>true,'choice_label' =>function ($choice,$key,$value) {returntrue ===$choice ?'Definitely!' :strtoupper($key);// or if you want to translate some key//return 'form.choice.'.$key; },));
Before:
useSymfony\Component\Form\Extension\Core\Type\ChoiceType;// ...$builder->add('attending', ChoiceType::class,array('choices' =>array('Yes' =>true,'No' =>false,'Maybe' =>null, ),'choices_as_values' =>true,'choice_attr' =>function($val,$key,$index) {// adds a class like attending_yes, attending_no, etcreturn ['class' =>'attending_'.strtolower($key)]; },));
After:
useSymfony\Component\Form\Extension\Core\Type\ChoiceType;// ...$builder->add('attending', ChoiceType::class,array('choices' =>array('Yes' =>true,'No' =>false,'Maybe' =>null, ),'choices_as_values' =>true,'choice_attr' =>function($choice,$key,$value) {// adds a class like attending_yes, attending_no, etcreturn ['class' =>'attending_'.strtolower($key)]; },));
I also recommend to add type hints in the advanced example:
Before:
useSymfony\Component\Form\Extension\Core\Type\ChoiceType;useAppBundle\Entity\Category;// ...$builder->add('category', ChoiceType::class, ['choices' => [newCategory('Cat1'),newCategory('Cat2'),newCategory('Cat3'),newCategory('Cat4'), ],'choices_as_values' =>true,'choice_label' =>function($category,$key,$index) {/** @var Category $category */returnstrtoupper($category->getName()); },'choice_attr' =>function($category,$key,$index) {return ['class' =>'category_'.strtolower($category->getName())]; },'group_by' =>function($category,$key,$index) {// randomly assign things into 2 groupsreturnrand(0,1) ==1 ?'Group A' :'Group B' },'preferred_choices' =>function($category,$key,$index) {return$category->getName() =='Cat2' ||$category->getName() =='Cat3'; },]);
After:
useSymfony\Component\Form\Extension\Core\Type\ChoiceType;useAppBundle\Entity\Category;// ...$builder->add('category', ChoiceType::class, ['choices' => [newCategory('Cat1'),newCategory('Cat2'),newCategory('Cat3'),newCategory('Cat4'), ],'choices_as_values' =>true,'choice_label' =>function(Category$category,$key,$value) {returnstrtoupper($category->getName()); },'choice_attr' =>function(Category$category,$key,$value) {return ['class' =>'category_'.strtolower($category->getName())]; },'group_by' =>function(Category$category,$key,$value) {// randomly assign things into 2 groupsreturnrand(0,1) ==1 ?'Group A' :'Group B' },'preferred_choices' =>function(Category$category,$key,$index) {return$category->getName() =='Cat2' ||$category->getName() =='Cat3'; },]);