2012-01-06 3 views
3

У меня есть поле коллекции с элементами выбора типа в моей форме Symfony. Каждый элемент должен иметь разные варианты выбора. Как я могу организовать это в Symfony2? Я не могу использовать параметр choices, потому что каждый элемент будет иметь одинаковые варианты. Я видел параметр choice_list, который принимает объект, который может создавать список параметров, но я не вижу, как он может создавать разные варианты для разных элементов в коллекции.Возможно ли иметь поле сбора в форме Symfony2 с различными вариантами?

Любая идея, как с этим бороться?

+0

Не могли бы вы рассказать нам о вашем конкретном случае? Что вы пытаетесь достичь? Я не совсем понял, что вы имеете в виду ... –

+0

Как и выше, я не совсем понимаю, что вы имеете в виду. Возможно, вы могли бы использовать __construct в своей форме для передачи выбора форме в зависимости от объекта, который является «объектом данных», который вы обрабатываете. –

ответ

3

Я думаю, вам нужна форма события: http://symfony.com/doc/current/cookbook/form/dynamic_form_generation.html.

Чтобы изменить способ сбора по умолчанию.

Основная форма проста:

namespace Acme\Bundle\AcmeBundle\Form; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilder; 

use Acme\Bundle\AcmeBundle\Form\DescriptorDumpFieldsType; 

class TranscodingType extends AbstractType 
{ 
    public function buildForm(FormBuilder $builder, array $options) 
    { 
     $builder->add('descriptorDumpFields', 'collection', array('type' => new DescriptorDumpFieldsType())); 
    } 

    public function getDefaultOptions(array $options) 
    { 
     return array(
      'data_class' => 'Acme\Bundle\AcmeBundle\Entity\Descriptor', 
     ); 
    } 

    public function getName() 
    { 
     return 'descriptor'; 
    } 
} 

Просто простая форма с набором вспомогательных форм.

Второй использует абонента формы, который обрабатывает создание формы. (используя события формы)

Итак, первая форма создана normaly и добавляет много DescriptorDumpFieldsType, которые динамически создаются.

namespace Acme\Bundle\AcmeBundle\Form; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilder; 
use Symfony\Component\Form\FormTypeInterface; 

use Acme\Bundle\AcmeBundle\Form\EventListener\TranscodingSubscriber; 

class DescriptorDumpFieldsType extends AbstractType 
{ 
    public function buildForm(FormBuilder $builder, array $options) 
    { 
     $subscriber = new TranscodingSubscriber($builder->getFormFactory()); 
     $builder->addEventSubscriber($subscriber); 
    } 

    public function getDefaultOptions(array $options) 
    { 
     return array(
      'data_class' => 'Acme\Bundle\AcmeBundle\Entity\DescriptorDumpField', 
     ); 
    } 

    public function getName() 
    { 
     return 'desc_dump_field'; 
    } 
} 

Форма подписчик:

namespace Acme\Bundle\AcmeBundle\Form\EventListener; 

use Symfony\Component\Form\Event\DataEvent; 
use Symfony\Component\Form\FormFactoryInterface; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\Form\FormEvents; 

use Acme\Bundle\AcmeBundle\Entity\DumpField; 

use Acme\Bundle\AcmeBundle\Form\Transcoding\DataTransformer\JsonToHumanDateTransformer; 

class TranscodingSubscriber implements EventSubscriberInterface 
{ 
    private $factory; 

    public function __construct(FormFactoryInterface $factory) 
    { 
     $this->factory = $factory; 
    } 

    public static function getSubscribedEvents() 
    { 
     return array(FormEvents::SET_DATA => 'setData'); 
    } 

    public function setData(DataEvent $event) 
    { 
     $data = $event->getData(); 
     $form = $event->getForm(); 

     if (!is_null($data)) { 
      $this->buildForm($data, $form);    
     } 
    } 

    protected function buildForm($data, $form) 
    { 
     switch ($data->getDumpField()->getType()) { 
      case DumpField::TYPE_ENUM: 
       $type = 'enum'.ucfirst($data->getDumpField()->getKey()); 
       $class = 'dump_field_'.strtolower($data->getDumpField()->getKey()); 
       $form->add($this->factory->createNamed('collection', 'transcodings', null, array('required' => false, 'type' => $type, 'label' => $data->getDumpField()->getKey(), 'attr' => array('class' => $class)))); 
       break; 
      case DumpField::TYPE_DATE: 
       $transformer = new JsonToHumanDateTransformer(); 
       $class = 'dump_field_'.strtolower($data->getDumpField()->getKey()); 
       $builder = $this->factory->createNamedBuilder('human_date', 'params', null, array('label' => $data->getDumpField()->getKey(), 'attr' => array('class' => $class))); 
       $builder->prependNormTransformer($transformer); 
       $form->add($builder->getForm()); 
       break; 
     } 
    } 
} 

Таким образом, вы можете настроить так, как вы хотите, каждый суб-формы сбора в buildForm.

+0

Спасибо, я работал на меня. – ninsky