首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Symfony6中的级联动态添加字段

Symfony6中的级联动态添加字段
EN

Stack Overflow用户
提问于 2022-04-11 09:41:46
回答 1查看 39关注 0票数 1

我有一个表格,上面有三个下拉选项:

FieldA FieldB FieldC

FieldB的选择依赖于fieldA的选择,FieldC的选择依赖于fieldB的选择

这些关系是:

代码语言:javascript
复制
EntityB ManyToMany EntityA

EntityC ManyToOne EntityB

一切正常,说明提交表单无效,错误是“此表单不应包含额外字段”,罪魁祸首是fieldC。

我做错什么了?

下面是我的FormType代码:

代码语言:javascript
复制
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('fieldA', EntityType::class, [
                'class' => EntityA::class,
                'choice_label' => 'name',
                'query_builder' => function(EntityARepository $a) {
                    return $a->createQueryBuilder('a')
                        ->orderBy('a.name', 'ASC');
                },
            ])

        ;

        $builder->get('fieldA')->addEventListener(
          FormEvents::POST_SUBMIT,
          function(FormEvent $event) {
              $form = $event->getForm();
              $this->setupFieldB(
                  $form->getParent(),
                  $form->getData()
              );
          }
        );

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function(FormEvent $event) {
                $data = $event->getData();
                if (!$data or !isset($data['fieldA'])) {
                    return;
                }
                $this->setupFieldB(
                    $event->getForm(),
                    $data['fieldA']
                );
            }
        );

        if ($builder->has('fieldB')) {
            $builder->get('fieldB')->addEventListener(
                FormEvents::POST_SUBMIT,
                function (FormEvent $event) {
                    $form = $event->getForm();
                    $this->setupFieldC(
                        $form->getParent(),
                        $form->getData()
                    );
                }
            );
        }

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) {
                $data = $event->getData();
                if (!$data or !isset($data['fieldB'])) {
                    return;
                }
                $this->setupFieldC(
                    $event->getForm(),
                    $data['fieldB']
                );
            }
        );
    }

    private function setupFieldB(FormInterface $form, ?string $selectedfieldA)
    {
        if (is_null($selectedfieldA)) {
            $form->remove('fieldB');
            $form->remove('fieldC');
            return;
        } else {
            $fieldA = $this->EntityARepository->findOneBy(['name' => $selectedfieldA]);
            $form
                ->add('fieldB', EntityType::class, [
                    'class' => EntityB::class,
                    'query_builder' => function (EntityBRepository $b) use ($fieldA) {
                        return $b->createQueryBuilder('b')
                            ->andWhere(':fieldA MEMBER of b.fieldAs')
                            ->setParameter('fieldA', $fieldA)
                            ->orderBy('b.name', 'ASC');
                    },
                    'choice_label' => 'name',
                ]);
        }
    }

    private function setupFieldC(FormInterface $form, ?string $selectedFieldB)
    {
        if (is_null($selectedFieldB)) {
            $form->remove('fieldC');
            return;
        } else {
            $fieldB = $this->fieldBRepository->findOneBy(['name' => $selectedFieldB]);
            $form
                ->add('fieldC', EntityType::class, [
                    'class' => EntityC::class,
                    'query_builder' => function(EntityCRepository $c) use ($fieldB) {
                        return $c->getQueryBuilderWithFilter(['fieldB' => $fieldB]);
                    },
                    'choice_label' => 'name',
                ]);
        }
    }
EN

回答 1

Stack Overflow用户

发布于 2022-04-14 08:47:28

经过进一步的研究,我找到了以下解决方案:

( a)用if ($builder->has('fieldB')) {删除该部分--因为这始终被解析为false。

( b)重写函数setupFieldB .如下所示:

代码语言:javascript
复制
private function setupFieldB(FormInterface $form, ?string $selectedfieldA)
{
    if (is_null($selectedfieldA)) {
        $form->remove('fieldB');
        $form->remove('fieldC');
        return;
    } else {
        $fieldA = $this->EntityARepository->findOneBy(['name' => $selectedfieldA]);
        
        $newBuilder = $form->getConfig()->getFormFactory()->createNamedBuilder('fieldB', 
            EntityType::class, null, [
                'class' => EntityB::class,
                'query_builder' => function (EntityBRepository $b) use ($fieldA) {
                    return $b->createQueryBuilder('b')
                        ->andWhere(':fieldA MEMBER of b.fieldAs')
                        ->setParameter('fieldA', $fieldA)
                        ->orderBy('b.name', 'ASC');
                },
                'choice_label' => 'name',
            ]);
        
        // now we can add the listener:
        $newBuilder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
            $form = $event->getForm();
            $this->setupFieldC(
                $form->getParent(),
                $form->getData()
            );
        });
        
        // finally add the field to the form
        $form->add($newBuilder->getForm());
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71825683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档