Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony form - Access Entity inside child entry Type in a CollectionType

Tags:

I'm trying to access the entity for a given embedded form in the parent CollectionType inside FormBuilder:

ParentType

Class ParentType extends AbstractType {     public function buildForm(FormBuilderInterface $builder, array $options)     {         $builder->add('children', CollectionType::class, array(             'entry_type' => ChildType::class         );     } } 

ChildType

class ChildType extends AbstractType {     public function buildForm(FormBuilderInterface $builder, array $options)     {         $child = $builder->getData(); // this returns null     }      public function getDefaultOptions(array $options)     {         return array(             'data_class' => 'Vendor\Bundle\Entity\Child',         );     } } 

While this works in a normal form, $child is being returned as null. How can I access the Child entity inside ChildType?

like image 553
Nick Avatar asked Mar 15 '12 16:03

Nick


2 Answers

The answer lies in using Event Listeners which listen for the PRE_SET_DATA event.

It will pass your closure a FormEvent class which contains both the form and the data being bound to it.

public function buildForm(FormBuilderInterface $builder, array $options) {     $builder->addEventListener(FormEvents::PRE_SET_DATA,         function (FormEvent $event) use ($builder)         {             $form = $event->getForm();             $child = $event->getData();              if ($child instanceof Child) {                  // Do what ever you like with $child entity data              }         }     ); } 
like image 131
user1207727 Avatar answered Oct 01 '22 00:10

user1207727


This is a more detailed solution based on user1207727.

Parent Type

class FrontentStatsInputFormType extends AbstractType {      public function buildForm(FormBuilderInterface $builder, array $options)     {         $builder             ->add('records', CollectionType::class, array(                 'entry_type' => FrontendStatsRecordType::class,                 'allow_add' => false,                 'allow_delete' => false,                 'label' => null,             ))         ;     }      public function configureOptions(OptionsResolver $resolver)     {         $resolver->setDefaults(array(             'data_class' => null         ));     } } 

Child Type

class FrontendStatsRecordType extends AbstractType {     public function buildForm(FormBuilderInterface $builder, array $options)     {         $builder->addEventListener(FormEvents::PRE_SET_DATA,             function (FormEvent $event) use ($builder)             {                 $form = $event->getForm();                 $child = $event->getData();                  if ($child instanceof StatsRecord) {                      // Do what ever you like with $child entity data                     // $child->getSomeValue();                      $form->add('value', TextType::class);                 }             }         );      }      public function configureOptions(OptionsResolver $resolver)     {         $resolver->setDefaults(array(             'data_class' => 'AppBundle\Entity\StatsRecord',         ));     }  } 

Create form in controller

public function indexAction(Request $request, InputForm $inputForm) {      $data = array();      foreach ($inputForm->getStatsTemplates() as $template) {         $statsRecord = new StatsRecord();         $data['records'][] = $statsRecord;     }       $form = $this->createForm('AppBundle\Form\FrontentStatsInputFormType', $data);     $form->handleRequest($request);       if ($form->isSubmitted() && $form->isValid()) {          $em = $this->getDoctrine()->getManager();          // Get entries and persist them in the database         $records = $form->get('records')->getData();         foreach ($records as $record) {             $em->persist($record);         }          $em->flush();          return $this->redirectToRoute('frontend_index');     }      return $this->render('frontend/showInputForm.html.twig', array(         'inputForm' => $inputForm,         'form' => $form->createView(),     )); } 
like image 28
segli Avatar answered Oct 01 '22 00:10

segli