2013-11-11 2 views
4

У меня есть форма с 3-зависимыми полей:Symfony2 Dynamic/зависимые формы

Производителя -> ManufacturerProductGroup -> ManufacturerProductSeries

Так что я хочу, чтобы выбрать изготовитель, на основе Производителя Группы продуктов и на основе ProductGroup серии продуктов.

Существует запись в CookBook о том, как бороться с такими динамическими формами, как , она легко работает на ManufacturerProductGroup. Проблема в том, что ManufacturerProductSeries зависит от другой динамической формы/поля.

Проблема заключается в том, что я не могу добавить прослушиватель в закрытие, поскольку у меня есть только доступ к FormInterface уже не к FormBuilderInterface.

Я не могу сделать это только с одним слушателем, как у слушателя PRE_SET_DATA, так как форма будет отправлена ​​затем, которая предотвратит любые изменения. Мне нужен способ добавить прослушиватель динамически или, возможно, обновить только данные в прослушивателе POST_SUBMIT и не заменять все поле/форму.

Это код, который выдает ошибку, так как я добавляю слушатель к несуществующему полю формы (manufacturerProductGroup доступна только после pre_set_data события)

/** 
* @param FormBuilderInterface $builder 
* @param array    $options 
*/ 
public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('manufacturer', 'entity', array('class' => 'ArticleBundle:manufacturer', 'empty_value' => false)); 

    $manufacturerProductGroupModifier = function(FormInterface $form, Manufacturer $manufacturer) 
    { 
     $manufacturerProductGroups = $this->em->getRepository('ArticleBundle:ManufacturerProductGroup') 
      ->findAvailableByManufacturer($manufacturer); 

     $form->add(
      'manufacturerProductGroup', 
      'entity', 
      array(
       'class' => 'ArticleBundle:ManufacturerProductGroup', 
       'empty_value' => '', 
       'choices' => $manufacturerProductGroups 
      ) 
     ); 
    }; 

    $manufacturerProductSeriesModifier = function(FormInterface $form, ManufacturerProductGroup $manufacturerProductGroup) 
    { 
     $manufacturerProductSeries = $this->em->getRepository('ArticleBundle:ManufacturerProductSeries') 
      ->findAvailableByManufacturerProductGroup($manufacturerProductGroup); 

     $form->add(
      'manufacturerProductSeries', 
      'entity', 
      array(
       'class' => 'ArticleBundle:ManufacturerProductSeries', 
       'empty_value' => '', 
       'choices' => $manufacturerProductSeries 
      ) 
     ); 

    }; 

    $builder->addEventListener(
     FormEvents::PRE_SET_DATA, 
     function(FormEvent $event) use ($manufacturerProductGroupModifier, $manufacturerProductSeriesModifier) { 
      /** @var $article Article */ 
      $article = $event->getData(); 
      $manufacturerProductGroupModifier($event->getForm(), $article->getManufacturer()); 
      $manufacturerProductSeriesModifier($event->getForm(), $article->getManufacturerProductGroup()); 
     } 
    ); 

    $builder->get('manufacturer')->addEventListener(
     FormEvents::POST_SUBMIT, 
     function(FormEvent $event) use ($manufacturerProductGroupModifier) { 
      $manufacturer = $event->getForm()->getData(); 
      $manufacturerProductGroupModifier($event->getForm()->getParent(), $manufacturer); 
     } 
    ); 

    $builder->get('manufacturerProductGroup')->addEventListener(
     FormEvents::POST_SUBMIT, 
     function(FormEvent $event) use ($manufacturerProductSeriesModifier) { 
      $manufacturerProductGroup = $event->getForm()->getData(); 
      $manufacturerProductSeriesModifier($event->getForm()->getParent(), $manufacturerProductGroup); 
     } 
    ); 
} 
+0

Вы нашли решение по вашему вопросу? – parisssss

+0

Я нашел https://speakerdeck.com/webmozart/symfony2-forms-past-present-future, чтобы быть хорошим источником. –

ответ

3

Я решил вопрос с помощью следующего кода :

$addManufacturerProductSeries = function (FormEvent $event) { 
     $form = $event->getForm()->getParent(); 
     $manufacturerProductGroup = $event->getData(); 

     $form->add(
      'manufacturerProductSeries', 
      'entity', 
      array(
       'auto_initialize' => false, 
       'class' => 'ArticleBundle:ManufacturerProductSeries', 
       'query_builder' => function (ManufacturerProductSeriesRepository $repository) use ($manufacturerProductGroup) { 
        return $repository->findAvailableByManufacturerProductGroupQueryBuilder($manufacturerProductGroup); 
       }, 
      ) 
     ); 
    }; 

    $addManufacturerProductGroup = function (FormEvent $event) use ($factory, $addManufacturerProductSeries) { 
     $form = $event->getForm()->getParent(); 
     $manufacturer = $event->getData(); 

     $fieldBuilder = $factory->createNamedBuilder(
      'manufacturerProductGroup', 
      'entity', 
      null, 
      array(
       'auto_initialize' => false, 
       'class' => 'ArticleBundle:ManufacturerProductGroup', 
       'query_builder' => function (ManufacturerProductGroupRepository $repository) use ($manufacturer) { 
        return $repository->findAvailableByManufacturerQueryBuilder($manufacturer); 
       }, 
      ) 
     ); 

     $fieldBuilder->addEventListener(FormEvents::POST_SET_DATA, $addManufacturerProductSeries); 
     $fieldBuilder->addEventListener(FormEvents::POST_SUBMIT, $addManufacturerProductSeries); 

     $form->add($fieldBuilder->getForm()); 
    }; 

    $builder->get('manufacturer')->addEventListener(FormEvents::POST_SET_DATA, $addManufacturerProductGroup); 
    $builder->get('manufacturer')->addEventListener(FormEvents::POST_SUBMIT, $addManufacturerProductGroup); 
+0

это возвращает ошибку 'option auto_initialize' не существует. что этот вариант делает? и как я могу его реализовать? – parisssss

+0

Возможно, этот вариант устарел. Вы должны попробовать удалить его. – marcoshoya

Смежные вопросы