【问题标题】:Is it possible to have collection field in Symfony2 form with different choices?Symfony2 表单中的集合字段是否可以有不同的选择?
【发布时间】:2012-01-06 10:37:47
【问题描述】:

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

知道如何处理吗?

【问题讨论】:

  • 您能告诉我们您的具体案例吗?你想要完成什么?我不太明白你的意思...
  • 像上面一样,我不太明白你的意思。也许您可以在表单中使用 __construct 将选择传递给表单,具体取决于您正在处理的“数据对象”对象。

标签: symfony twig


【解决方案1】:

我认为您需要表单事件: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中集合的每个子表单。

【讨论】:

    猜你喜欢
    • 2013-12-19
    • 1970-01-01
    • 2010-09-18
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多