Symfony2: две формы на одной странице

У меня две формы на одной странице.

Моя проблема в том, когда я попытался отправить форму, она вроде бы попыталась представить вторую форму ниже на странице.

Как и далее, вы можете найти мои 2 формы:

public function createSuiviForm() {

    return $form = $this->createFormBuilder(null)
            ->add('numero', 'text', array('label' => 'N° : ',
                'constraints' => array(
                    new Assert\NotBlank(array('message' => 'XXXX')),
                    new Assert\Length(array('min' => 19, 'max' => 19, 'exactMessage' => 'XXX {{ limit }} XXX')))))
            ->add('xxxx', 'submit')
            ->getForm();
}

public function createModificationForm() {

    return $form = $this->createFormBuilder(null)
            ->add('modification', 'submit', array('label' => 'XXXXXXXXXXXXXXXXXXXX'))
            ->getForm();
}

Моя вторая форма - только кнопка отправки.

Я передал их своему рендерингу и отобразил их, используя:

<div class="well">
    <form method="post" action='' {{form_enctype(form)}} >
        {{ form_widget(form) }}
        <input type="submit" class="btn btn-primary"/>
    </form>
    <div class='errors'>
        {{ form_errors(form) }}
     </div>
</div>

'form' - это имя моей переменной в первой форме и 'update' для моей второй формы.

Когда я попытался представить свою вторую форму, мне нужно дважды щелкнуть, и, наконец, я получаю:

"This form should not contain extra fields."
And all non valid input for the remainding form.

Я попытался добавить validation_group в false, но безрезультатно.

Я не понимаю, почему я получил эту ошибку, потому что мои формы не встроены вообще

Надеюсь, вы поймете...

Ответы

Ответ 2

Это помогло в Symfony 3 (также должен работать на Symfony 2):

$form1 = $this->createForm(
    MyFirstFormType::class
);

$form2 = $this->createForm(
    MySecondFormType::class
);

if ($request->isMethod('POST')) {

    $form1->handleRequest($request);
    $form2->handleRequest($request);

    if ($form1->isSubmitted()) {
        // Handle $form1
    } else if ($form2->isSubmitted()) {
        // Handle $form2
    }

}

Ответ 3

Проблема заключается в том, что у вас есть две безымянные формы (введите имена, такие как inputname вместо formname[inputname]), и, таким образом, когда вы привязываете запрос к своей форме и его проверяете, он обнаруживает некоторые дополнительные поля (другая форма) и поэтому он недействителен.

Кратковременное решение заключается в создании именованного конструктора с помощью формы factory, поэтому вместо:

$form = $this->createFormBuilder(null)

вы должны использовать:

$form = $this->get("form.factory")->createNamedBuilder("my_form_name")

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

Ответ 4

Две формы будут опубликованы.

Попробуйте использовать:

    $this->createNamedBuilder 

вместо

    $this->createFormBuilder

Затем в вашем контроллере найдите форму по имени:

if ($request->request->has("your form name") {
   $form->handleRequest($request);
}

Ответ 5

Вот как я обрабатываю их на контроллере:

return $this->render('SgaDemandeBundle:Demande:suivi_avancement.html.twig', 
                     array('form' => $form->createView(), 
                           ........
                           'update' => $formModification->createView()));

Это html для второй формы:

<div class="well">
    <form method="post">
        <div id="form">
            <div>
                <button type="submit" id="form_modification"  
                name="form[modification]">Modification done
                </button>
            </div>
            <input type="hidden" id="form__token" name="form[_token]" 
            value="fFjgI4ecd1-W70ehmLHmGH7ZmNEHAMqXlY1WrPICtK4">
        </div>        
    </form>
</div>

Это моя веточка:

<div class="well">
    <form method="post" {{form_enctype(update)}} >
        {{ form_widget(update) }}
    </form>
</div>

<div class="well">
    <form method="post" action='' {{form_enctype(form)}} >
        {{ form_widget(form) }}
        <input type="submit" class="btn btn-primary"/>
    </form>
     <div class='errors'>
        {{ form_errors(form) }}
     </div>
</div>

Надеюсь, это поможет вам.

Ответ 6

Использование именных форм - это жизнеспособное решение для обработки нескольких форм, но оно может немного запутаться, особенно если вы динамически генерируете формы.

Другой метод, как Symfony 2.3, - проверить, какая кнопка отправки нажата.

Например, если предположить, что каждая форма имеет кнопку отправки с именем 'save':

if ('POST' == $Request->getMethod())
{
    $form1->handleRequest($Request);
    $form2->handleRequest($Request);
    $form3->handleRequest($Request);

    if ($form1->get('save')->isClicked() and $form1->isValid())
    {
        //Do stuff with form1
    }

    if ($form2->get('save')->isClicked() and $form2->isValid())
    {
        //Do stuff with form2
    }

    if ($form3->get('save')->isClicked() and $form3->isValid())
    {
        //Do stuff with form3
    }
}

Я считаю, что у этого есть небольшое количество дополнительных накладных расходов по сравнению с методом named builder (из-за нескольких вызовов handleRequest), но в некоторых случаях это приводит к более чистым кодам. Всегда хорошо иметь несколько решений на выбор. Некоторые дополнительные накладные расходы можно было бы облегчить с помощью вложенных операторов if/else, если это необходимо, но, если мы не говорим о десятках форм на странице, дополнительные накладные расходы в любом случае ничтожны.

Здесь альтернативная реализация с использованием анонимных функций, которая сводит к минимуму повторение кода:

$form1Action = function ($form) use (&$aVar) {
        //Do stuff with form1
    };
$form2Action = function ($form) use (&$anotherVar) {
        //Do stuff with form2
    };
$form3Action = function ($form) use (&$yetAnotherVar) {
        //Do stuff with form3
    };
$forms = [$form1 => $form1Action, 
          $form2 => $form2Action,
          $form3 => $form3Action];

if ('POST' == $Request->getMethod())
{
    foreach ($forms as $form => $action)
    {
        $form->handleRequest($Request);
        if ($form->get('save')->isClicked() and $form->isValid())
        {
            $action($form);
        }
    }
}

Ответ 7

Посмотрите на префикс блока:

public function getBlockPrefix()
{
    return 'app_x_form'.$form_id;
}