Как отправить и сохранить форму Symfony и необязательную вложенную форму?

Я использую два типа форм для одной страницы в моем проекте Symfony. Я делаю это, чтобы пользователь мог выбирать между двумя вариантами создания нового документа тип формы

Как устроена страница: есть несколько текстовых полей, которые нужно заполнить. Все они относятся к моему DocumentCreateType, а также включают правую часть выбора (выберите IATA вручную), которую вы видите на картинке. Мой второй тип формы (UploadProfileType) содержит те же три раскрывающихся списка плюс дополнительный (рынки, канал 1 и продукты), но на левом сайте по выбору (используйте профили загрузки).

Таким образом, в зависимости от того, что выбрал пользователь, необходимо отправить только DocumentCreateType или оба типа формы должны быть отправлены и сохранены.

Как я могу заставить это работать в моем контроллере? Пока мой контроллер выглядит так, но он неправильно сохраняет данные.

  $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())
    {
    ...
    }

ChoiceType для выбора между профилем загрузки и IATA выглядит так и обрабатывается 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'))

            ;
          }

person sonja    schedule 19.12.2017    source источник
comment
Создайте простой переключатель в своем представлении и в своем контроллере проверьте, который был выбран, и выполните действия с ответом...   -  person Smaïne    schedule 19.12.2017
comment
@Smaïne какой ответ? или какие вещи вы имеете в виду?   -  person sonja    schedule 19.12.2017


Ответы (2)


Несколько форм

В HTTP вы можете иметь только одну отправленную форму по запросу.

Создайте конечную точку для каждой отправки формы, где вы отправляете только одну форму.

Создать документ A -> createADDocumentAction()

Создать документ B -> createBDocumentAction()

Одна форма для всего

Если вы вызываете форму для набора данных, но все отправляется с помощью одного запроса, вы должны создать Symfony From (Type), который содержит все данные двух форм Symfony, которые вы планируете отправить.

person albert    schedule 19.12.2017
comment
Я не могу использовать одну форму, так как я использую EntityTypes одних и тех же сущностей в двух моих формах. Только с одной формой я бы не смог иметь два раскрывающихся списка для одних и тех же объектов. Способ с несколькими формами кажется очень избыточным, поскольку это всего лишь одна небольшая часть действия. - person sonja; 19.12.2017
comment
Вы можете иметь столько раскрывающихся списков, сколько хотите в форме. Неважно, к какому типу сущностей они относятся. - person albert; 20.12.2017
comment
нет, у меня не может быть двух раскрывающихся списков из одного и того же объекта. Я не могу продавать раскрывающиеся списки - person sonja; 20.12.2017
comment
Пожалуйста, загрузите свои формы по вашему вопросу, и я обновлю код для нескольких раскрывающихся списков. - person albert; 20.12.2017

Вы не можете отправить две формы одновременно, это либо одно, либо другое. Поэтому я бы предложил вам создать две разные формы:

  • Первый будет отправлен, когда будет выбрано «Использовать профиль загрузки».

  • Второй будет отправлен, когда будет выбрано «Выбрать IATA вручную».

В каждой из форм нужно указать все данные. Если вы хотите избежать дублирования кода в FormType, вы можете создать настраиваемый тип формы (не связанный с сущностью):

<?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 */
        );
    }
}

Для обработки обеих форм в контроллере:

/* 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 */
));

Затем с помощью JavaScript, в зависимости от того, какой переключатель выбран, вы отображаете либо первую форму (с собственной кнопкой отправки), либо вторую (также с собственной кнопкой отправки).

person Nicolas    schedule 19.12.2017