Symfony表单 | 动态集合类型值

3
我正在Symfony 3.4上构建一个小工具,我遇到了两个关于表单的问题,但是我无法找到解决方案。
为了背景说明,引起困难的表单基于Doctrine实体:Event。该事件引用另一个实体:一个Doctrine(与ORM无关)。Doctrine引用多个配件。 对于给定的具有给定Doctrine的事件,我想显示从Doctrine配件构建的集合类型,以公开此配件所需数量的数字。
这导致我的表单中有3个实体:事件本身,Doctrine和由我构建的FittingRequirements的CollectionType。

Here is how it looks

右侧面板内容旨在随着教义的更改而更改。
以下是 EventType:
<?php

namespace AppBundle\Form;

use AppBundle\Entity\Doctrine;
use AppBundle\Entity\Event;
use AppBundle\Form\DataTransformer\FittingRequirementTransformer;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class EventType extends AbstractType
{
    protected $requirementTransformer;

    public function __construct(FittingRequirementTransformer $transformer)
    {
        $this->requirementTransformer = $transformer;
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder
            ->setMethod('POST')
            ->add('name')
            ->add(
                'date',
                DateTimeType::class,
                [
                    'widget' => 'single_text',
                    'format' => 'yyyy-MM-dd HH:mm',
                ]
            )
            ->add('startLocation')
            ->add(
                'eventType',
                ChoiceType::class,
                [
                    'choices' => [
                        'PvE'   => 'PvE',
                        'PvP'   => 'PvP',
                        'Other' => 'Other',
                    ],
                ]
            )
            ->add('target')
            ->add('description')
            ->add(
                'doctrine',
                EntityType::class,
                [
                    'class'         => 'AppBundle\Entity\Doctrine',
                    'choice_label'  => 'name',
                    'query_builder' => function (EntityRepository $repository) {
                        return $repository->createQueryBuilder('d')->orderBy('d.name', 'ASC');
                    },
                    'required'      => false,
                ]
            );


        $formModifier = function (FormInterface $form, Doctrine $doctrine = null, Event $event) {

            $eventRequirements = [];

            if ($doctrine) {

                $doctrineFittings     = $doctrine->getFittings();
                $doctrineRequirements = $event->getDoctrineFittingRequirements($doctrine);

                $eventRequirements = $this->requirementTransformer->dataToForm(
                    $doctrineFittings,
                    $doctrineRequirements,
                    $event
                );

            }

            $form->add(
                'eventRequirements',
                CollectionType::class,
                [
                    'entry_type'    => FittingRequirementType::class,
                    'label'         => false,
                    'entry_options' => ['label' => false],
                    'data'          => $eventRequirements,
                    'mapped'        => false,
                ]
            );

        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier) {

                $formupEvent = $event->getData();
                $formModifier($event->getForm(), $formupEvent->getDoctrine(), $formupEvent);
            }
        );

        $builder->get('doctrine')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($formModifier) {

                $eventForm = $event->getForm()->getParent();
                $doctrine  = $event->getForm()->getData();
                $formModifier($event->getForm()->getParent(), $doctrine, $eventForm->getData());
            }
        );
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(
            [
                'data_class' => 'AppBundle\Entity\Event',
            ]
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'event';
    }
}

我正在构建事件适配要求列表,并在 PRE_SET_DATA 和 POST_SUBMIT 中添加它。 如您所见,我使用 FittingRequirementType 的 CollectionType,如下所示:
<?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class FittingRequirementType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('number', NumberType::class);
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\FittingRequirement'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_fittingrequirement';
    }
}

这仅用于公开所需配件的数量。

当我显示表单时,所有这些都很好运作,但是当我使用JavaScript提交表单以刷新要求部分时,字段确实被替换,但返回的表单中输入框没有值。

来自我的 $formModifier 的 $eventRequirements 变量包含 适当的数据集,具有数字值。然而,当我使用 Symfony 分析器检查 XHR 时,表单没有值,即使我再次选择原始 Doctrine。我不明白发生了什么以及如何解决这个问题。

感谢您的阅读。

1个回答

1
我刚刚发现了问题并解决了它。
我的表单没问题,但是handleRequest方法清除了我用自定义fittingRequirement列表设置的未映射字段。
我不得不手动提交表单,并将clearmissing参数设置为false,如下所示:
$form->submit($request->request->get($form->getName()), false);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接