Reputation: 2821
I have many fields of type subclass of EntityType, something like this:
$builder->add('managers', SubclassEntityType::class, [
'class' => 'User',
'choice_label' => 'Managers',
'required' => false,
'query_builder' => function (UserRepository $er) {
return $er->getManagersQueryBuilder();
},
'multiple' => true,
]);
$builder->add('types', SubclassEntityType::class, [
'class' => 'Type',
'choice_label' => 'Types',
'required' => false,
'query_builder' => function (TypesRepository $er) {
return $er->getManagersQueryBuilder();
},
'multiple' => true,
]);
Could I dynamically add option (option of fields in select, not option of form) to all fields of the same type like this (Empty) => 'empty? I don't want to customize it for each field. I need this option to filter allow to add to field null values, for examples, find entities to which not manager is assigned. Would it be easier to solve this if it were subclass of ChoiceType?
I tried to subclass ChoiceType и add empty option in buildView, but in this case validation fails as well. Does anybody know how to add option and make validation work? It looks like adding option in buildView doesn't solve the problem.
Upvotes: 0
Views: 285
Reputation: 173
if isn't multiple ,You can achieve that by defining tow options placeholder and empty_data
class YourType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('managers', SubclassEntityType::class, [
'placeholder' => 'Please choose a manager..',
'empty_data' => null,
'class' => 'User',
'choice_label' => 'Managers',
'required' => false,
'query_builder' => function (UserRepository $er) {
return $er->getManagersQueryBuilder();
},
]);
$builder->add('types', SubclassEntityType::class, [
'placeholder' => 'Please choose a type..',
'empty_data' => null,
'class' => 'User',
'class' => 'Type',
'choice_label' => 'Types',
'required' => false,
'query_builder' => function (UserRepository $er) {
return $er->getManagersQueryBuilder();
},
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
// ...
]);
}
}
For multiple choices we can use finishView method for creating new choices and add them on children of your type.
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class YourType extends AbstractType
{
// If you have in the future other type Entity Type and you want to add option empty
// You can just add it on this list
private const OPTION_EMPTY_ENTITIES_TYPE = [
// child name => 'Message on option empty',
'managers' => 'Select a manager..',
'types' => 'Select a type..',
];
private const OPTION_EMPTY_KEY ='option-empty';
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('managers', SubclassEntityType::class, [
'class' => 'User',
'choice_label' => 'Managers',
'required' => false,
'query_builder' => function (UserRepository $er) {
return $er->getManagersQueryBuilder();
},
'multiple' => true,
]);
$builder->add('types', SubclassEntityType::class, [
'class' => 'Type',
'choice_label' => 'Types',
'required' => false,
'query_builder' => function (UserRepository $er) {
return $er->getManagersQueryBuilder();
},
'multiple' => true,
]);
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
// remove all options we has add on finishView
foreach (self::OPTION_EMPTY_ENTITIES_TYPE as $childName => $optionMessage) {
if (false !== ($key = array_search(self::OPTION_EMPTY_KEY ,$data[$childName]))) {
unset($data[$childName][$key]); // example $data['managers'][0] => option-empty
}
}
$event->setData($data);
});
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
foreach (self::OPTION_EMPTY_ENTITIES_TYPE as $childName => $optionMessage) {
// value option-empty is not a valid option of EntityType X ,otherwise if user select this option
// this form is invalid...
$newChoice = new ChoiceView(null, self::OPTION_EMPTY_KEY, $optionMessage);
array_unshift($view->children[$childName]->vars['choices'], $newChoice);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
// ..
]);
}
}
Upvotes: 1