Symfony2 Form Events - Dropdown Lists

On the Symfony2 website, I am trying to create a form with a drop-down list of 2 (or 3) with dependencies such as Country> Region> City. And this city is the field of the element that I edit using the form. The idea is to fill out lists depending on the choice.

I followed the tutorial with event forms here: http://aulatic.16mb.com/wordpress/2011/08/symfony2-dynamic-forms-an-event-driven-approach/ (which is based on webb-on-the-web .com /? p = 5)

The problem I encountered: it all works, but when I use the form to edit the item, the city is selected correctly (from the database), but the Country and Region drop-down lists are filled in and left to "select a value". I do not know if it should work with the textbook as it is.

Question: how can I make these lists selected? I am trying to add a POST_SET_DATA event, but cannot find a way to select a value in the form field.

Here is the form class: http://pastebin.com/PpWkHxC3 (note that instead of the city it is: Field> Subject and subject - this is the lesson field that is editing the form).

+8
symfony
source share
1 answer

I almost had it. If someone else needs this, then what needs to be added so that this solution works fine when editing an existing element:

class ItemDetailForm extends AbstractType { ... $builder->addEventListener(FormEvents::POST_SET_DATA, function (DataEvent $event) use ($refreshTopic) { $data = $event->getData(); $form = $event->getForm(); if (null === $data) { return; } $form->get('region')->setData($data->getCity()->getRegion()); }); } 

Edit: starting with symfony 2.1, the POST_SET_DATA event is raised before children are added to the form, forcing all get ('region') to throw an exception. The solution is to create this field in POST_SET_DATA, and not in buildForm ():

  /** @var FormFactory $factory */ $form->add($factory->createNamed('region', 'entity', null, array( 'class'=>'AcmeBundle:Region', 'property_path'=>false, 'empty_value'=>'Choose a value', 'required'=>true, 'label'=>'Region' ))); 

Note that you need to add $ factory to the "use" of event handling closure:

 $builder->addEventListener(FormEvents::POST_SET_DATA, function (DataEvent $event) use ($refreshTopic, $factory) { 

Here is the whole form class:

 <?php namespace AAA\CoreBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Doctrine\ORM\EntityRepository; use AAA\CoreBundle\Entity\ClassYear; use AAA\CoreBundle\Entity\Field; use AAA\CoreBundle\Entity\Lesson; use AAA\CoreBundle\Form\LessonContentForm; class LessonDetailForm extends AbstractType { public $country; function __construct($country=null) { // Get country for classyear dropdown list $this->country = $country; } public function buildForm(FormBuilderInterface $builder, array $options) { $factory = $builder->getFormFactory(); $builder->add('name', null, array('label'=>'Titre de la leçon')); $builder->add('description', 'textarea', array('label'=>'Description (définition conceptuelle) Qu\'est-ce que c\'est ? Et à quoi ça sert ? (importance, utilité)')); $builder->add('text', 'textarea', array('label'=>'Leçon', 'required'=>false)); // Can't set 'required' on textareas used by TinyMCE $builder->add('reperes', 'textarea', array('label'=>'Repères (détectionel) - Quels sont les éléments qui me permettent de repérer que je dois penser à ce concept ?', 'required'=>false)); $builder->add('other_topic', null, array( 'required' => false, 'mapped' => false )); $refreshField = function ($form, $classyear) use ($factory) { /** @var FormFactory $factory */ /** @var Form $form */ $form->add($factory->createNamed('field','entity',null, array( 'class' => 'AAA\CoreBundle\Entity\Field', 'mapped' => false, 'label' => 'Matière', 'empty_value' => 'Sélectionne une valeur', 'empty_data' => null, 'required' => false, 'query_builder' => function (EntityRepository $repository) use ($classyear) { $qb = $repository->createQueryBuilder('field') ->innerJoin('field.classyear', 'classyear'); if($classyear instanceof ClassYear) { $qb = $qb->where('field.classyear = :classyear') ->setParameter('classyear', $classyear); } elseif(is_numeric($classyear)) { $qb = $qb->where('classyear.id = :classyear_id') ->setParameter('classyear_id', $classyear); } else { $qb = $qb->where('0 = 1'); } return $qb; } ))); }; $refreshTopic = function ($form, $field) use ($factory) { /** @var FormFactory $factory */ /** @var Form $form */ $form->add($factory->createNamed('topic','entity',null, array( 'class' => 'AAA\CoreBundle\Entity\Topic', 'property' => 'name', 'label' => 'Sujet', 'empty_value' => 'Sélectionne une valeur', 'empty_data' => null, 'required' => false, 'query_builder' => function (EntityRepository $repository) use ($field) { $qb = $repository->createQueryBuilder('topic') ->innerJoin('topic.field', 'field'); if($field instanceof Field) { $qb = $qb->where('topic.field = :field') ->setParameter('field', $field); } elseif(is_numeric($field)) { $qb = $qb->where('field.id = :field_id') ->setParameter('field_id', $field); } else { $qb = $qb->where('0 = 1'); } return $qb; } ))); }; // Populate ddl to show form $country = $this->country; $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($refreshTopic, $refreshField, $factory, $country) { /** @var Lesson $data */ $data = $event->getData(); $form = $event->getForm(); // Test if null because this event is called 2 times, only the second time with the actual Lesson object (which has null values in the creation case) if($data != null) // In case of creation if($data->getId()==null) { // Creates empty fields $refreshTopic($form, null); $refreshField($form, null); } // In case of edition else { if ($data->getTopic() != null) { $refreshTopic($form, $data->getTopic()->getField()); if ($data->getTopic()->getField() != null) { $refreshField($form, $data->getTopic()->getField()->getClassYear()); } } else { $refreshField($form, null); $refreshTopic($form, null); } } /** @var FormFactory $factory */ $form->add($factory->createNamed('classyear', 'entity', null, array( 'class' => 'AAACoreBundle:ClassYear', 'property' => 'name'.$country, 'mapped' => false, 'label' => 'Année', 'empty_value' => 'Sélectionne une valeur', 'empty_data' => null, 'required' => false, 'query_builder' => function (EntityRepository $repository) { return $repository->createQueryBuilder('classyear') ->orderBy('classyear.sort'); } ))); }); // Populate ddl when form was posted $builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) use ($refreshTopic, $refreshField) { $form = $event->getForm(); $data = $event->getData(); if(array_key_exists('classyear', $data)) { $refreshField($form, $data['classyear']); } if(array_key_exists('field', $data)) { $refreshTopic($form, $data['field']); } }); // Select value in ddl when editing $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) use ($refreshTopic) { /** @var Lesson $data */ $data = $event->getData(); $form = $event->getForm(); if (null === $data || null === $data->getId() ) { return; } if ($data->getTopic() != null) { $form->get('field')->setData($data->getTopic()->getField()); if ($data->getTopic()->getField() != null) { $form->get('classyear')->setData($data->getTopic()->getField()->getClassYear()); } } }); } public function getName() { return 'LessonDetailForm'; } /** @param OptionsResolverInterface $resolver */ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'AAA\CoreBundle\Entity\Lesson' )); } } ?> 
+10
source share

All Articles