2012-01-06 58 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

相關問題