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, но безрезультатно.
Я не понимаю, почему я получил эту ошибку, потому что мои формы не встроены вообще
Надеюсь, вы поймете...
Ответы
Ответ 1
Вы должны обрабатывать формы отдельно:
if('POST' === $request->getMethod()) {
if ($request->request->has('form1name')) {
// handle the first form
}
if ($request->request->has('form2name')) {
// handle the second form
}
}
Это прекрасно объясняется в Symfony2 Несколько форм: разные из встроенных форм
Ответ 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;
}