2012-03-15 8 views
19

Estoy intentando acceder a la entidad durante un formulario incrustado dado en la matriz CollectionType dentro FormBuilder:forma Symfony - Acceso Entidad en el interior del niño Tipo de entrada en una CollectionType

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

Mientras esto funciona s en una forma normal, $child se devuelve como nulo. ¿Cómo puedo acceder a la entidad Child dentro de ChildType?

Respuesta

38

La respuesta está en utilizar Escuchadores de eventos que escuchan el evento PRE_SET_DATA.

Pasará su cierre una clase FormEvent que contiene tanto la forma como los datos que se le atribuyen.

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 

      } 
     } 
    ); 
} 
+1

Solicitar al qu obvia estion, ¿definitivamente tiene algún Bares en su entidad matriz que se utiliza para los datos del formulario? ¿Puedes verificar al var_dumping tu colección de barras de los datos en tu tipo de formulario principal? – user1207727

+0

¡Maravilloso, gracias! Esto funcionó perfectamente, y también me llevó a la parte en los documentos que pasé por alto: [Cómo generar formas dinámicamente mediante eventos de formulario] (http://symfony.com/doc/current/cookbook/form/dynamic_form_generation.html) – Nick

+0

Ah , captó mi comentario antes de que lo borrara, excluí perezosamente la parte de su respuesta con el formulario, tratando de continuar con el propio constructor. Entonces decidí usar tu solución textualmente, y funcionó. Perdón por confundir! – Nick

2

Esta es una solución más detallada basada en user1207727.

tipo padre

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

Tipo Niño

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

} 

Crear formulario en el controlador

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(), 
    )); 
} 
Cuestiones relacionadas