2012-01-06 57 views
3

我在Symfony窗​​体中有一个类型选择元素的集合字段。每个元素应该有不同的列表选项。我如何安排在Symfony2中?我不能使用choices选项,因为每个元素都有相同的选项。我见过choice_list选项,它带有一个可以产生选项列表的对象,但我不明白它如何为集合中的不同元素产生不同的选择。有没有可能让Symfony2形式的收藏领域有不同的选择?

任何想法如何处理?

+0

你能告诉我们你的具体情况吗?你想要完成什么?我不太明白你的意思... – 2012-01-17 16:51:01

+0

像上面一样,我不太明白你的意思。也许你可以在表单中使用__construct来根据你正在处理的'数据对象'的对象传递选项到表单。 – 2012-01-22 12:49:25

回答

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

只是一个简单的表格的子窗体的集合。

第二个使用处理表单创建的表单订户。 (使用表单事件)

因此,第一种形式正常创建并添加许多动态创建的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

感谢toine,为我工作。 – ninsky 2015-04-25 16:11:03

相关问题