Symfony:表单包含可选的附加表单 - >如何提交&坚持正确 [英] Symfony: Form contains optional additional form --> how to submit & persist both correctly

查看:130
本文介绍了Symfony:表单包含可选的附加表单 - >如何提交&坚持正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Symfony项目中为一个页面使用了两种表单类型。我这样做是为了让用户决定创建一个新文档的两个选项:



页面的构建方式:有几个文本字段,要填写。它们全部属于我的 DocumentCreateType ,并且还包含您可以在图片中看到的选择的右侧部分(手动选择IATA)。我的第二种表单类型( UploadProfileType )包含相同的三个下拉菜单和一个附加的下拉菜单(市场,渠道1和产品),但位于选择的左侧站点上(使用上传配置文件)。



因此,根据用户的选择,只需提交DocumentCreateType,或者两种表单类型都必须提交并保存。



我如何在我的控制器中使其工作?到目前为止,我的控制器看起来像这样,但它不能正确保存数据。



$ $ $ $ $ $ $ $ $ $ $ :class,$ document,array('user'=> $ currentuser));
$ form = $ this-> createForm(DocumentCreateType :: class,$ document);

$ form-> handleRequest($ request);
$ upForm-> handleRequest($ request);

if($ form-> isSubmitted()& $ amp; $ form-> isValid())
{
...
}

上传配置文件和IATA之间选择的ChoiceType类似,并由javascript处理:


$ b $

  $ builder 

- > add('use_upload_profile',ChoiceType :: class,array(
'options'=> array(
true =>'label.use_upload_profile',
false =>'label.select_iatas_manually'
),
'mapped'=> ; false,
'expanded'=> true,
'label'=> false,
'data'=> true,
'translation_domain'=>' Documents'))

;
}

预先致谢

解决方案

您无法同时提交两种表单,它们都是其中一种。所以我建议你创建两种不同的表单:


  • 第一个将在使用上传配置文件被选中


  • 第二个将在选择手动选择IATA时提交

  • / ul>

    在每个表单中,您需要提交所有数据。如果您想避免FormType中的重复代码,您可以创建一个自定义表单类型(不与实体关联):

      <?php 
    // src / AppBundle / Form / Custom / CustomFormType.php

    命名空间AppBundle \Form\Custom;

    使用Symfony \Component\Form\Extension\Core\Type\FormType;
    $ b $ class CustomFormType
    {
    / **
    *创建'上传配置文件'自定义表单(不与类关联)
    * $ b $的b * @参数类型$ formFactory
    * @参数类型$ defaultData
    * @返回类型
    * /
    公共函数createUploadProfileCustomForm($ formFactory,$ defaultData)
    {
    / *创建'上传配置文件'表单(不关联到一个类)* /
    $ form = $ formFactory-> createBuilder(FormType :: class,$ defaultData,array());

    $ this-> addMarkets($ form);
    $ this-> addChannel1($ form);
    $ this-> addProducts($ form);

    / *添加其他需要的字段* /
    $ form-> add(...);

    * *返回表单* /
    return $ form-> getForm();
    }

    / **
    *创建'select IATA manual'自定义表单(不关联到类)
    *
    * @param type $ formFactory
    * @参数类型$ defaultData
    * @返回类型
    * /
    公共函数createSelectIATAManuallyCustomForm($ formFactory,$ defaultData)
    {
    / *创建'手动选择IATA'表单(不关联到类)* /
    $ form = $ formFactory-> createBuilder(FormType :: class,$ defaultData,array());

    $ this-> addMarkets($ form);
    $ this-> addChannel1($ form);
    $ this-> addProducts($ form);

    / *添加其他需要的字段* /
    $ form-> add(...);

    * *返回表单* /
    return $ form-> getForm();


    保护函数addMarkets($ form)
    {
    $ form-> add('markets',...
    / * To完成* /
    );

    $ b保护功能addChannel1($ form)
    {
    $ form-> add('channel1',...
    / * To完成* /
    );

    $ b $保护功能addProducts($ form)
    {
    $ form-> add('products',...
    / * To完成* /
    );


    code $


    在控制器中处理这两种形式:

      / *创建'上传配置文件'表单(不关联到类)* / 
    $ defaultDataUP = array(.. );
    $ customFormTypeUP = new CustomFormType();
    $ formUploadProfile = $ customFormTypeUP-> createUploadProfileCustomForm($ this-> get('form.factory'),$ defaultDataUP);
    $ formUploadProfile - > handleRequest($ request);
    $ b $ *创建'select IATA manual'表单(不关联到一个类)* /
    $ defaultDataSM = array(...);
    $ customFormTypeSM = new CustomFormType();
    $ formSelectManually = $ customFormTypeSM-> createSelectIATAManuallyCustomForm($ this-> get('form.factory'),$ defaultDataSM);
    $ formSelectManually - > handleRequest($ request);
    $ b $ *如果($ formUploadProfile-> isSubmitted()& $ formUploadProfile-> isValid(如果用户选择上传配置文件并提交了相关表单* /
    )){

    / *做一些动作,坚持到数据库等等* /

    / *然后重定向用户* /
    返回新的RedirectResponse(。 ..);
    }
    / *否则,如果用户选择了手动选择并提交了关联的表单* /
    elseif($ formSelectManually-> isSubmitted()&& $ $ formSelectManually-> ; isValid()){

    / *做一些动作,坚持数据库等等* /

    / *然后重定向用户* /
    return new RedirectResponse(...);
    }

    * *渲染页面时,不要忘记在参数中传递两个表单* /
    return $ this-> render('yourPage.html.twig ,阵列(
    'form_upload_profile'=> $ formUploadProfile-> CreateView的(),
    'form_select_iata_manually'=> $ formSelectManually-> CreateView的(),
    / *添加其他你可能需要的参数* /
    ));

    然后,使用JavaScript,根据所选的单选按钮,显示第一个表单它自己的提交按钮)或第二个(也有它自己的提交按钮)。


    I'm using two form types for one page in my Symfony project. I do this to let the user decide between two options of creating a new document

    How the page is build: there are several text fields, to be filled out. They all belong to my DocumentCreateType and also include the right part of the choice (select IATA(s) manually) you can see in the picture. My second form type (UploadProfileType) contains the same three dropdowns plus an addtional one (markets, channel1 and products) but on the left site of the choice (use upload profile(s)).

    So depending on what the user has chosen, only the DocumentCreateType has to be submitted, or both form types have to be submitted and persisted.

    How can I make this working in my Controller? So far my Controller looks like that but it's not correctly persisting the data

      $upForm = $this->createForm(UploadProfileType::class, $document, array('user' => $currentuser));
        $form = $this->createForm(DocumentCreateType::class, $document);
    
          $form->handleRequest($request);
         $upForm->handleRequest($request); 
    
        if ($form->isSubmitted() && $form->isValid())
        {
        ...
        }
    

    The ChoiceType for the choice between upload profile and IATA looks like that and is handled by javascript:

      $builder
    
            ->add('use_upload_profile', ChoiceType::class, array(
                      'choices' => array(
                          true => 'label.use_upload_profile',
                          false => 'label.select_iatas_manually'
                      ),
                      'mapped' => false,
                      'expanded' => true,
                      'label' => false,
                      'data' => true,
                      'translation_domain' => 'Documents'))
    
                ;
              }
    

    Thanks in advance

    解决方案

    You cannot submit two forms at the same time, it's either one or the other. So I would suggest you create two different forms:

    • The first one will be submitted when "Use upload profile(s)" is selected

    • The second one will be submitted when "Select IATA(s) manually" is selected

    In each of the forms you need all the data to be submitted. If you want to avoid duplicated code in the FormType, you can create a Custom Form Type (not associated to an entity):

    <?php
    // src/AppBundle/Form/Custom/CustomFormType.php
    
    namespace AppBundle\Form\Custom;
    
    use Symfony\Component\Form\Extension\Core\Type\FormType;
    
    class CustomFormType
    {
        /**
         * Create the 'upload profile' custom form (not associated to a class)
         * 
         * @param type $formFactory
         * @param type $defaultData
         * @return type
         */
        public function createUploadProfileCustomForm($formFactory, $defaultData)
        {
            /* Create the 'upload profile' form (not associated to a class) */
            $form = $formFactory->createBuilder(FormType::class, $defaultData, array());
    
            $this->addMarkets($form);
            $this->addChannel1($form);
            $this->addProducts($form);
    
            /* Add whatever other field necessary */
            $form->add(...);
    
            /* Return the form */
            return $form->getForm();
        }
    
        /**
         * Create the 'select IATA manually' custom form (not associated to a class)
         * 
         * @param type $formFactory
         * @param type $defaultData
         * @return type
         */
        public function createSelectIATAManuallyCustomForm($formFactory, $defaultData)
        {
            /* Create the 'select IATA manually' form (not associated to a class) */
            $form = $formFactory->createBuilder(FormType::class, $defaultData, array());
    
            $this->addMarkets($form);
            $this->addChannel1($form);
            $this->addProducts($form);
    
            /* Add whatever other field necessary */
            $form->add(...);
    
            /* Return the form */
            return $form->getForm();
        }
    
        protected function addMarkets($form)
        {
            $form->add('markets', ...
                /* To complete */
            );
        }
    
        protected function addChannel1($form)
        {
            $form->add('channel1', ...
                /* To complete */
            );
        }
    
        protected function addProducts($form)
        {
            $form->add('products', ...
                /* To complete */
            );
        }
    }
    

    To handle both forms in the controller:

    /* Create the 'upload profile' form (not associated to a class) */
    $defaultDataUP = array(...);
    $customFormTypeUP = new CustomFormType();
    $formUploadProfile = $customFormTypeUP->createUploadProfileCustomForm($this->get('form.factory'), $defaultDataUP);
    $formUploadProfile ->handleRequest($request);
    
    /* Create the 'select IATA manually' form (not associated to a class) */
    $defaultDataSM = array(...);
    $customFormTypeSM = new CustomFormType();
    $formSelectManually = $customFormTypeSM->createSelectIATAManuallyCustomForm($this->get('form.factory'), $defaultDataSM);
    $formSelectManually ->handleRequest($request);
    
    /* If the user selected 'upload profile' and submitted the associated form */
    if ($formUploadProfile->isSubmitted() && $formUploadProfile->isValid()) {
    
        /* Do some action, persist to database, etc. */
    
        /* Then redirect the user */
        return new RedirectResponse(...);
    }
    /* Else, if the user selected 'select manually' and submitted the associated form */
    elseif ($formSelectManually->isSubmitted() && $formSelectManually->isValid()) {
    
        /* Do some action, persist to database, etc. */
    
        /* Then redirect the user */
        return new RedirectResponse(...);
    }
    
    /* Render the page, don't forget to pass the two forms in parameters */
    return $this->render('yourPage.html.twig', array(
        'form_upload_profile' => $formUploadProfile->createView(),
        'form_select_iata_manually' => $formSelectManually->createView(),
        /* Add other parameters you might need */
    ));
    

    Then, with JavaScript, depending on which radio button is selected, you display either the first form (with its own submit button) or the second (also with its own submit button).

    这篇关于Symfony:表单包含可选的附加表单 - &gt;如何提交&amp;坚持正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆