How to submit & persist a Symfony form and optiona

2019-08-28 04:48发布

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 form type

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'))

            ;
          }

2条回答
Deceive 欺骗
2楼-- · 2019-08-28 05:15

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).

查看更多
\"骚年 ilove
3楼-- · 2019-08-28 05:16

Multiple forms

In HTTP you can only have one submitted form on a request.

Create an endpoint for each form submit where you only submit one form.

Create Document A -> createADocumentAction()

Create Document B -> createBDocumentAction()

One form with everything

If you are calling form to a set of data but everything gets submited with a single request you should create a Symfony From (Type) that has all the data of the two symfony forms that you plan to submit.

查看更多
登录 后发表回答