当前位置: 动力学知识库 > 问答 > 编程问答 >

symfony2 - Access unmapped form data in form event

问题描述:

I want to create a dependend select box: if the first selectbox is selected, the second selectbox should be filled.

My first selectbox isn't mapped to the model. I set the value manually in my controller with $form->get('emailTemplateBlockType')->setData($emailTemplateBlockType) .. How can I use this data in my form event to create my second selectbox?

 $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;

});

I have an onChange event with jQuery that posts the choice of the first selectbox to my frontcontroller again. The front controller then creates the form again, but this time with the value of the first selectbox added. But since it's not a submit, I think using the POST_SUBMIT event will not work either.

Snippet from my controller:

 $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);

网友答案:

I think I finally nailed it. I'll describe my pitfalls here, for a full article on how I eventually implemented this see Forms in Symfony2: dependent selectboxes

First of all, it seems I have to submit the full form in order to trigger the form event PRE_SUBMIT. I couldn't just post one variable to the form.

Second, I totally missed that inside the PRE_SUBMIT event, the data is stored in an array instead of an object, which was actually perfectly mentioned in this post. So I should have used:

$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']);
    }
});

Third is that my unmapped form element can't be accessed in PRE_SET_DATA, but it can in POST_SET_DATA.

Fourth is that I was having issues when I would change the first selectbox, if I had already selected the first and second. This would make sense, because the value in the second selectbox would indeed be invalid, if the first selectbox would change. The easiest way to solve this was to just set the value to empty in the change event of the first selectbox.

I would also like to point out that this approach doesn't require any additional scripting in the controller or javascript when you add more dependent fields. All logic for this is done inside the form builder, so I think it creates better reusable code than the approach of Airam.

分享给朋友:
您可能感兴趣的文章:
随机阅读: