In Symfony, the built-in ChoiceType (and EntityType or DocumentType extending it), basicaly work with a constant choice list.
If you want to make it work with ajax calls, you have to change them to accept any sumitted extra choices.
How to start with an empty choice list ?
When you build your form, just set the choices
option to an empty array()
:
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class FooType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tag', ChoiceType::class, array('choices'=>array()));
}
}
So you will get an empty select input, without choices. This solution works for ChoiceType and all of his children (EntityType, DocumentType, ...).
How to accept submitted new choices :
To accept the new choices, you have to make them available in the form field choicelist. You can change your form field depending on submitted data with the FormEvent::PRE_SUBMIT event.
This example show how to do it with a basic ChoiceType :
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class FooType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tag', ChoiceType::class, array('choices'=>array()))
;
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function(FormEvent $event){
// Get the parent form
$form = $event->getForm();
// Get the data for the choice field
$data = $event->getData()['tag'];
// Collect the new choices
$choices = array();
if(is_array($data)){
foreach($data as $choice){
$choices[$choice] = $choice;
}
}
else{
$choices[$data] = $data;
}
// Add the field again, with the new choices :
$form->add('tag', ChoiceType::class, array('choices'=>$choices));
}
);
}
}
Your submitted choices are now allowed choices and Symfony ChoiceType built-in validation won't reject them anymore.
If you wan to do the same with a ChoiceType child (EntityType, DocumentType, ...), you have to inject the entityManager or the documentManager and to do the datatransformation when populating the new choices.