0

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.

1
  • I tried to subclass ChoiceType и add empty option in buildView, but in this case validation fails as well. Commented Sep 9, 2022 at 13:19

1 Answer 1

1

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([
            // ..
        ]);
    }


}
Sign up to request clarification or add additional context in comments.

1 Comment

Comments are not for extended discussion; this conversation has been moved to chat.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.