Symfony form - Access Entity inside child entry Type in a CollectionType
26,835
Solution 1
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
}
}
);
}
Solution 2
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(),
));
}
Related videos on Youtube
Author by
Nick
Updated on July 22, 2020Comments
-
Nick almost 4 years
I'm trying to access the entity for a given embedded form in the parent
CollectionType
insideFormBuilder
: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 theChild
entity insideChildType
? -
user1207727 about 12 yearsTo ask the obvious question, do you definitely have any Bars in your parent entity that's used for the form's data? Can you check by var_dumping your bars collection from the data in your parent form type?
-
Nick about 12 yearsWonderful, thanks! This worked perfectly, and also led me to the part in the docs I overlooked: How to Dynamically Generate Forms Using Form Events
-
Nick about 12 yearsAh, you caught my comment before I deleted it -- I lazily excluded the part of your answer with the formfactory, trying to continue with just the builder itself. I then decided to use your solution verbatim, and it worked. Sorry to confuse!
-
user1207727 about 12 yearsFantastic! I'm glad it worked for you. Some of this stuff can seem quite mysterious in comparison to symfony 1, but slowly I'm starting to see the light at the end of the tunnel :)
-
nni6 over 11 yearsGreat example. Thanks. But when I add fields in the function as it was previously discussed, the fields are not included in the prototype of collection. I need these fields in the prototype.. Is it real? How should I fix this?
-
Waiting for Dev... over 11 yearsDoes anybody have a simple explanation about why couldn't I do simply
$builder->add()
inside the anonymous function? -
AntonioCS about 9 yearsThis will not work in Symfony2.6. There is no DataEvent (you can still google and find a page with details of the class but the class is not included in Symfony2)
-
Pavel Dubinin over 8 yearsOn symfony 2.6. event class is
Symfony\Component\Form\FormEvent