如何在同一视图中处理同一实体类型的多个表单

Posted

技术标签:

【中文标题】如何在同一视图中处理同一实体类型的多个表单【英文标题】:How to handle multiple form for the same entity type in the same view 【发布时间】:2022-01-04 00:33:31 【问题描述】:

我想为一个表中的所有条目(只有两个字段)生成一个表单列表,只有一个保存和一个删除按钮。

这里是屏幕:https://i.imgur.com/4hW48Bw.png

这是表单部分:

模板\项目\品牌\_brandForm.html.twig

 form_start(formView) 
<div class="row justify-content-md-center">
    <div class="col col-lg-auto">
        #
        <br>
        brandId
    </div>
    <div class="col col-lg-3">
         form_row(formView.fullname) 
    </div>
    <div class="col col-lg-3">
         form_row(formView.icon) 
    </div>
    <div class="col col-lg-3 align-self-end">
        <button class="btn btn-primary" type="submit" name="update_button" value="brandId">
            <i class="fas fa-save"></i>
        </button>
        <button class="btn btn-danger" type="submit" name="delete_button" value="brandId">
            <i class="fas fa-trash-alt"></i>
        </button>
    </div>
</div>
 form_end(formView) 

这里是视图:

模板\项目\品牌\listForm.html.twig

% extends 'base.html.twig' %

% block title %Create a brand
% endblock %

% block body %
    <h1>Brand list form</h1>
    % for form in forms %
        form | raw
    % endfor %
% endblock %

这是表单类型:

class BrandType extends AbstractType

    public function buildForm(FormBuilderInterface $builder, array $options): void
    
        $builder
            ->add('fullname')
            ->add('icon');
    

    public function configureOptions(OptionsResolver $resolver): void
    
        $resolver->setDefaults([
            'data_class' => Brand::class,
        ]);
    

最后是控制器部分:

 public function editableList(EntityManagerInterface $em, Request $request, BrandRepository $brandRepository)
    
        $formHtml = [];
        $brands = $brandRepository->findAll();
        foreach ($brands as $brand) 
            $form = $this->createForm(BrandType::class, $brand);
            $form->handleRequest($request);
            if ($form->isSubmitted()) 
                dd($brand);
            
            $formHtml[] = $this->renderView('item/brand/_brandForm.html.twig', [
                'formView' => $form->createView(),
                'brandId' => $brand->getId(),
            ]);
        
        return $this->render('item/brand/listForm.html.twig', [
            'forms' => $formHtml,
        ]);
    

表单已正确生成,但当我提交其中一个表单时,它会返回一个具有正确提交数据但 ID 错误的实体(数据库返回的第一个)。

我试图弄清楚如何将 ID 传递给 POST 请求,但我被卡住了,因为我无法在提交的实体上设置 ID。也许我走错了路,但我敢肯定,我不会错过满足我这样需求的选择。

欢迎提出任何建议;)

【问题讨论】:

【参考方案1】:

我终于找到了解决方案。 诀窍是简单地创建以 ID 作为名称的命名表单。 我使用工厂来做到这一点。

这里是固定控制器:

/**
 * @Route("admin/item/brand/editable-list", name="admin_item_brand_editable-list")
 */
public function editableList(FormFactoryInterface $formFactoryInterface, EntityManagerInterface $em, Request $request, BrandRepository $brandRepository)

    $formHtml = [];
    $brands = $brandRepository->findAll();
    foreach ($brands as $brand) 
        $form = $formFactoryInterface->createNamedBuilder($brand->getId(), BrandType::class, $brand)->getForm();
        $form->handleRequest($request);
        if ($form->isSubmitted()) 
            if ($form->get('saveButton')->isClicked()) 
                $em->flush();
                $formHtml[] = $this->renderView('item/brand/_brandForm.html.twig', [
                    'formView' => $form->createView(),
                    'brandId' => $brand->getId(),
                ]);
             elseif ($form->get('deleteButton')->isClicked()) 
                $em->remove($brand);
                $em->flush();
             else 
                throw new ErrorException('un bouton doit être clické');
            
         else 
            $formHtml[] = $this->renderView('item/brand/_brandForm.html.twig', [
                'formView' => $form->createView(),
                'brandId' => $brand->getId(),
            ]);
        
    
    return $this->render('item/brand/listForm.html.twig', [
        'forms' => $formHtml,
    ]);

【讨论】:

以上是关于如何在同一视图中处理同一实体类型的多个表单的主要内容,如果未能解决你的问题,请参考以下文章

如何在应用程序端调用实体的视图

同一实体类型代码的多个一对多关系优先

如何在 Swift 的不同视图控制器中更新同一实体的属性?

JPA,如何使用同一个类(实体)来映射不同的表?

再次查询同一实体

为啥 Hibernate 在一对多双向更新操作中给出同一实体的多个表示?