Symfony2表单中的集合字段是否可以有不同的选择?

时间:2012-01-06 10:37:47

标签: symfony twig

我的Symfony表单中有一个包含所选类型元素的集合字段。每个元素应该有不同的列表o选择。我怎样才能在Symfony2中安排这个?我不能使用choices选项,因为每个元素都有相同的选择。我见过choice_list选项,它接受一个可以产生选项列表的对象,但我不知道它如何为集合中的不同元素产生不同的选择。

知道怎么处理吗?

1 个答案:

答案 0 :(得分: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中自定义您想要的方式,集合的每个子表单。

相关问题