Как добавить прослушиватель событий в динамически добавленное поле с помощью Symfony Forms

Я использую прослушиватели событий для динамического изменения формы. Я хочу добавить еще один прослушиватель событий в поле, которое было добавлено динамически. Я не уверен, как это сделать.

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 } 

Я просто использую $builder в функции buildForm чтобы добавить прослушиватель событий в second_field но поскольку поле не существует, когда форма изначально генерируется, она выдает ошибку.

Если я попытаюсь добавить нового прослушивателя событий в первый прослушиватель событий, выполните следующие действия:

 $form->get('second_field')->addEventListener(...) 

Тогда я получаю ошибку:

 Call to undefined method Symfony\Component\Form\Form::addEventListener() 

Любые предложения приветствуются.

Если это действительно так.

FormInterface не имеет метода addEventListener, но FormBuilderIntreface имеет его. Если вы хотите добавить слушателя, вы должны создать поле формы с помощью построителя форм.

Например:

  // 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()); 

Я только что потратил половину своего рабочего дня на это. Я использую symfony 3.2.x, и лучшее, что помогло мне, – это ответ .

У меня была тройная зависимость (страна, штат, регион, zipcode), я решил все внутри одного 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); } 

Каждая из этих функций обрабатывает одно из динамических полей, и они все одинаковы:

 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); }); } 

Просто измените ссылки на объекты для двух других функций: cityAjaxFieldFormListener и zipCodeAjaxFieldFormListener

Вам не нужно добавлять слушателя событий в first_field или second_field . Вы можете сохранить прослушиватель событий в родительской форме и проверить как представленные, так и установленные данные для того, first_field ли они данные для first_field . Если это так, добавьте second_field . В том же слушателе проверьте, были ли данные установлены или отправлены на second_field . Если это так, добавьте третье поле.

Существует аналогичная концепция, изложенная в документации: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data