在表单事件中访问未映射的表单数据

时间:2014-11-07 15:30:15

标签: symfony symfony-forms

我想创建一个dependend选择框:如果选择了第一个选择框,则应填充第二个选择框。

我的第一个选择框未映射到模型。我使用$form->get('emailTemplateBlockType')->setData($emailTemplateBlockType)在我的控制器中手动设置了值。如何在表格事件中使用此数据来创建我的第二个选择框?

    $builder
        ->add('emailTemplateBlockType', 'entity', array(
            'class' => 'MbDbMVibesBundle:EmailTemplateBlockType',
            'property' => 'name',
            'mapped' => false,
            'empty_value' => 'Choose a block type',
            'attr' => array(
                'class' => 'emailTemplateBlockTypeSelect',
            )
        ))
        ->add('save', 'submit');


    $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
        $form = $event->getForm();
        $data = $event->getData();

            echo "name: ".$form->get('emailTemplateBlockType')->getData()->getName();
            die;
    });

我有一个带有jQuery的onChange事件,它将第一个选择框的选择再次发布到我的前控制器。然后前控制器再次创建表单,但这次添加了第一个选择框的值。但由于它不是提交,我认为使用POST_SUBMIT事件也不起作用。

来自我的控制器的片段:

    $form = $this->createForm(new EmailTemplateSiteEmailTemplateBlockType(), $entity, array(
        'action' => $this->generateUrl('_email_tpl_site_block_edit', array(
            'emailTemplateSiteId' => $emailTemplateSiteId,
            'emailTemplateSiteBlockId' => $emailTemplateSiteBlockId,
        ))
    ));

    if ($request->request->get('blockTypeId')) {
        $this->get('logger')->debug('setting block type');

        $emailTemplateBlockType = $em->getRepository('MbDbMVibesBundle:EmailTemplateBlockType')
            ->find($request->request->get('blockTypeId'));

        if ($emailTemplateBlockType)
            $form->get('emailTemplateBlockType')->setData($emailTemplateBlockType);
        else
            throw new $this->createNotFoundException('Cannot find blocktype with id '.$request->request->get('blockTypeId'));

    }

    $form->handleRequest($request);

1 个答案:

答案 0 :(得分:2)

我想我终于把它钉了下来。我将在这里描述我的陷阱,有关我最终如何实现这一点的完整文章,请参阅Forms in Symfony2: dependent selectboxes

首先,似乎我必须提交完整的表单才能触发表单事件PRE_SUBMIT。我无法将一个变量发布到表单中。

其次,我完全错过了在PRE_SUBMIT事件中,数据存储在数组而不是对象中,这在this post中实际上是完全提到的。所以我应该使用:

$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($addEmailTemplateBlock) {
    $form = $event->getForm();
    $data = $event->getData();

    if (array_key_exists('emailTemplateBlockType', $data)) {
        $addEmailTemplateBlock($form, $data['emailTemplateBlockType']);
    }
});

第三,我的未映射的表单元素无法在PRE_SET_DATA中访问,但它可以在POST_SET_DATA中访问。

第四,如果我已经选择了第一个和第二个选择框,那么当我更改第一个选择框时,我遇到了问题。这是有道理的,因为如果第一个选择框会改变,第二个选择框中的值确实无效。解决此问题的最简单方法是在第一个选择框的更改事件中将值设置为空。

我还想指出,当您添加更多依赖字段时,此方法在控制器或javascript中不需要任何其他脚本。所有逻辑都是在表单构建器中完成的,所以我认为它创建了比Airam更好的可重用代码。