我在Symfony窗体中有一个类型选择元素的集合字段。每个元素应该有不同的列表选项。我如何安排在Symfony2中?我不能使用choices
选项,因为每个元素都有相同的选项。我见过choice_list选项,它带有一个可以产生选项列表的对象,但我不明白它如何为集合中的不同元素产生不同的选择。有没有可能让Symfony2形式的收藏领域有不同的选择?
任何想法如何处理?
我在Symfony窗体中有一个类型选择元素的集合字段。每个元素应该有不同的列表选项。我如何安排在Symfony2中?我不能使用choices
选项,因为每个元素都有相同的选项。我见过choice_list选项,它带有一个可以产生选项列表的对象,但我不明白它如何为集合中的不同元素产生不同的选择。有没有可能让Symfony2形式的收藏领域有不同的选择?
任何想法如何处理?
我认为你需要表单事件: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集合的每个子表单。
感谢toine,为我工作。 – ninsky 2015-04-25 16:11:03
你能告诉我们你的具体情况吗?你想要完成什么?我不太明白你的意思... – 2012-01-17 16:51:01
像上面一样,我不太明白你的意思。也许你可以在表单中使用__construct来根据你正在处理的'数据对象'的对象传递选项到表单。 – 2012-01-22 12:49:25