How to add an Event Listener to a dynamically added field using Symfony Forms
Solution 1
If, is it actually.
FormInterface does't have the addEventListener method, but FormBuilderIntreface have it. If you want to add any listener, you should to create form field by form builder.
For example:
// create builder for field
$builder = $form->getConfig()->getFormFactory()->createNamedBuilder($name, $type, null, array(
/** any options **/
'auto_initialize'=>false // it's important!!!
));
// now you can add listener
$builder->addEventListener(FormEvents::POST_SUBMIT, $yourCallbackHere)
// and only now you can add field to form
$form->add($builder->getForm());
Solution 2
I have just spent half of my working day struggling on this. I'm using symfony 3.2.x and the best thing that helped me is this answer.
I had a triple dependece (country,state,region,zipcode) i've solved all inside the same FormType:
/** @var EntityManager $em */
private $em;
/**
* GaraFormType constructor.
*
* @param EntityManager $em
*/
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('country', EntityType::class, array(
'class' => 'Country',
...more attrs
));
$this->stateAjaxFieldFormListener($builder);
$this->cityAjaxFieldFormListener($builder);
$this->zipCodeAjaxFieldFormListener($builder);
}
Each of those functions handles one of the dynamic fields, and they are all the same as follows:
private function stateAjaxFieldFormListener(FormBuilderInterface $builder)
{
$localizationFormModifier = function (FormInterface $form, Country $country = null) {
$stateInCountry = $this->em->getRepository("State")->findBy(array("country" => $country));
if ($form->has('state') && ! $form->isSubmitted()) {
$form->remove('state');
}
$form
->add('state', EntityType::class, array(
'choices' => $stateInCountry,
'class' => 'State',
));
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($localizationFormModifier) {
/** @var ClienteTemp $data */
$data = $event->getData();
$country = null !== $data ? $data->getCountry() : null;
$localizationFormModifier($event->getForm(), $country);
});
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($localizationFormModifier) {
$data = $event->getData();
$countryId = array_key_exists('country', $data) ? $data['country'] : null;
$country = $this->em->getRepository("Country")->find($countryId);
$localizationFormModifier($event->getForm(), $country);
});
}
Just change entity references for the other two functions: cityAjaxFieldFormListener and zipCodeAjaxFieldFormListener
Chase
Development has been a passion of mine for a very long time! They say if you love what you do then you never work a day in your life. Id say thats mostly true. I have opinions on almost everything and strong opinions on some things. I really enjoying hearing opposing views and discussing and debating the merits of all sides!
Updated on June 05, 2022Comments
-
Chase almost 2 years
I am using event listeners to dynamically modify a form. I want to add another event listener to a field that was added dynamically. Im not sure how to accomplish this.
public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('first_field','choice',array( 'choices'=>array('1'=>'First Choice','2'=>'Second Choice') )); $builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'preSetData')); $builder->get('first_field')->addEventListener(FormEvents::POST_SUBMIT, array($this, 'postSubmit')); } public function preSetData(FormEvent $event) { $form = $event->getForm(); $form->add('second_field','choice',array( 'choices'=>array('1'=>'First Choice','2'=>'Second Choice') )); //Some how add an event listener to this field } public function postSubmit(FormEvent $event) { $form = $event->getForm()->getParent(); $form->add('second_field','choice',array( 'choices'=>array('1'=>'First Choice','2'=>'Second Choice') )); //Some how add an event listener to this field }
I have trie just using the
$builder
in thebuildForm
function to add the event listener to thesecond_field
but because the field doesnt exist when the form is initially generated it throws an error.If i try and add the new event listener inside the first event listener by doing:
$form->get('second_field')->addEventListener(...)
Then i get the error:
Call to undefined method Symfony\Component\Form\Form::addEventListener()
Any suggestions would be welcome.