【发布时间】:2013-10-14 08:42:01
【问题描述】:
我在 symfony2 上遇到了动态表单的问题。我正在尝试为提交的表单生成一些字段。换句话说,用户输入一些值,提交表单,根据这些值,我的动态字段被添加到同一个表单中(显然,这是第二次显示)。为此,我使用了食谱中的这个例子:http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data
所以,这是我的 FormationType 类
class FormationType extends AbstractType
{
private $em;
private $context;
public function __construct($em, $context) {
$this->em = $em;
$this->context = $context;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('date')
->add('type', 'choice', array(
'mapped' => false,
'choices' => Formationlist::getTypeTypes(false),
'empty_value' => false,
))
->add('cost')
->add('travelCost')
->add('maximum')
->add('location')
->add('schedule')
;
$formModifier = function(FormInterface $form, $type) {
$formationList = $this->em->getRepository('CoreBundle:FormationList')->findBy(array("year" => 1, "type" => $type));
$form->add('formationList', 'entity', array(
'label'=> 'Titre formation',
'choices' => $formationList,
'class' => 'CoreBundle:FormationList',
'property' => 'title',)
);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event) use ($formModifier) {
$data = $event->getForm();
$type = $data->get('type')->getData();
$formModifier($event->getForm(), $type);
}
);
$builder->get('type')->addEventListener(
FormEvents::POST_SUBMIT,
function(FormEvent $event) use ($formModifier) {
$type = $event->getForm()->getData();
$formModifier($event->getForm()->getParent(), $type);
}
);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'EXAMPLE\CoreBundle\Entity\Formation'
));
}
public function getName()
{
return 'example_corebundle_formationtype';
}
}
所以,这两个 addEventListener 工作得很好。第一次显示我的表单时,formModifier 中的字段未按预期加载。我的控制器类如下:
public function createAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$contextSrv = $this->get('example.service.context');
$context = $contextSrv->getContext();
$entity = new Formation();
$form = $this->createForm(new FormationType($em, $context), $entity);
$form->bind($request);
if ($form->isValid()) {
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('formation_show', array('id' => $entity->getId())));
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
由于我的一个动态字段不能为空,所以第一次提交表单时,它是无效的。因此,FormationType 被第二次加载。这意味着,如果字段“类型”被填充,我的 formModifier() 函数可以加载动态字段(formationList)。在那之前,一切都很好,我得到了我的新领域。
但是,在表单上“提交”第二次之后……什么也没有发生。页面刚刚重新加载,并没有显示任何错误。
我用
检查了表单内容var_dump($request->request->get('example_corebundle_formationtype'));
-> 每个字段(包括动态字段)都填充了有效值。
我也试试这个:
foreach($form->all() as $item) {
echo $item->getName();
var_dump($item->getErrors());
}
-> 这些行没有显示任何错误。但是,表单永远无效。
var_dump($form->isValid());
-> 它返回 false。所以表格无效。
最后,如果我删除整个动态部分,我的表单就可以工作了。 我不明白出了什么问题。表单没有显示错误,并且 csrf 令牌似乎正确。我错过了什么 ?感谢您的帮助。
【问题讨论】:
-
只是一个猜测,当你删除这行代码时,你能用萤火虫检查 类型的值是否相同:'choices' => $formationList, from your form $formModifier ?
-
嗯...我不明白你的意思。我从 $formModifier 中删除了 'choices' => $formationList,但字段“type”没有发生任何事情。这是预期的,因为“类型”是没有动态值的选择。 formationList 字段过去是,现在仍然是一个列表(
-
内的 应该是 FormationList 类的有效 id(无论您指定什么主键),否则 $form->isValid() 将为 false。这是我的观点,但我很确定列表 $formationList 做得很好,因此它应该有正确的 id。这只是一个疯狂的猜测。
-
添加一个 {{ form_errors(form) }} 以在视图上打印所有表单错误。也许您在实体函数上有一些验证器?
-
似乎错误冒泡已禁用。你试过设置error_bubbling => true吗?此外,您指的是 2.4 文档。您使用的是 Symfony 2.4.x 吗?如果是这样,Profiler 有一个 Form 部分。跟踪发生的事情可能很有用。