In symfony3 i have base view and inside this one im rendering other controller (this controller render form (return view with form - form is method POST)) when i try to use this one on the page object Request-isMethod() always return GET how to fix it.
Part of base view: (main controller show welcome page and render inside this one)
<li><a>{{ render(controller('CommonUserBundle:Login:login')) }}</a></li>
Form login type
class LoginType extends AbstractType
{
public function getName()
{
return 'login_form';
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->
add('username', TextType::class, array(
'label' => 'Użytkownik'
))
->add('password', PasswordType::class, array(
'label' => 'Hasło'
))
->add('remember_me', CheckboxType::class, array(
'label' => 'Zapamiętaj mnie'
))
->add('save', SubmitType::class, array(
'label' => 'Zaloguj'
));
}
}
Controller that render the form above
/**
* #Route("/", name="login")
*
* #Template
*/
public function loginAction(Request $Request)
{
$Session = $this->get('session');
if($Request->attributes->has(Security::AUTHENTICATION_ERROR)){
$loginError = $Request->attributes->get(Security::AUTHENTICATION_ERROR);
} else {
$loginError = $Session->remove(Security::AUTHENTICATION_ERROR);
}
$loginForm = $this->createForm(LoginType::class, array(
'username' => $userName = $Session->get(Security::LAST_USERNAME)
));
return array(
'loginError' => $loginError,
'loginForm' => $loginForm->createView()
);
}
Twig of above
<button type="button" class="btn btn-success btn-sm" data-toggle="modal" data-target="#loginForm">
Zaloguj
</button>
<div class="modal fade" id="loginForm" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Logowanie</h4>
{% if loginError is defined and loginError is not null %}
<div class="">
Blad i chuj: {{ loginError.message }}
</div>
{% endif %}
</div>
<div class="modal-body">
{% form_theme loginForm 'bootstrap_3_layout.html.twig' %}
{{ form(loginForm, {'action': path('_check_path')}) }}
</div>
<div class="modal-footer">
{{ render(controller('CommonUserBundle:Login:rememberPassword')) }}
<button type="button" class="btn btn-default" data-dismiss="modal">Zamknij</button>
</div>
</div>
</div>
</div>
So as i said, i render this form on other twig tempalte and after i click SUBMIT my Request->getMethod is GET. In html all is ok method="post", when i create other Route only to this form his own (not rendered) its working ok. How to change it to work ok?
Related
I want to generate a list of form for all entries in a table (just two fields) with just a save and a delete button.
Here is the screen : https://i.imgur.com/4hW48Bw.png
Here is the form part :
templates\item\brand\_brandForm.html.twig
{{ form_start(formView) }}
<div class="row justify-content-md-center">
<div class="col col-lg-auto">
#
<br>
{{brandId}}
</div>
<div class="col col-lg-3">
{{ form_row(formView.fullname) }}
</div>
<div class="col col-lg-3">
{{ form_row(formView.icon) }}
</div>
<div class="col col-lg-3 align-self-end">
<button class="btn btn-primary" type="submit" name="update_button" value="{{brandId}}">
<i class="fas fa-save"></i>
</button>
<button class="btn btn-danger" type="submit" name="delete_button" value="{{brandId}}">
<i class="fas fa-trash-alt"></i>
</button>
</div>
</div>
{{ form_end(formView) }}
Here is the view :
templates\item\brand\listForm.html.twig
{% extends 'base.html.twig' %}
{% block title %}Create a brand
{% endblock %}
{% block body %}
<h1>Brand list form</h1>
{% for form in forms %}
{{form | raw}}
{% endfor %}
{% endblock %}
Here is the FormType :
class BrandType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('fullname')
->add('icon');
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Brand::class,
]);
}
}
And finally here is the controller part :
public function editableList(EntityManagerInterface $em, Request $request, BrandRepository $brandRepository)
{
$formHtml = [];
$brands = $brandRepository->findAll();
foreach ($brands as $brand) {
$form = $this->createForm(BrandType::class, $brand);
$form->handleRequest($request);
if ($form->isSubmitted()) {
dd($brand);
}
$formHtml[] = $this->renderView('item/brand/_brandForm.html.twig', [
'formView' => $form->createView(),
'brandId' => $brand->getId(),
]);
}
return $this->render('item/brand/listForm.html.twig', [
'forms' => $formHtml,
]);
}
Forms are correctly generated but when I submit one of them it returns a entity with the correct submitted data but with the wrong ID (the first one returned by the database).
I tried to figure out how to pass the ID to the POST request but I'm stuck because I can't set ID on the submitted entity. Maybe I'm on the wrong way, but I would be sure that I'm not missing an option to achieve my need like that.
Any suggestion will be welcome ;)
Finally I found the solution.
The trick was simply to create named form with ID as name.
I use the factory to do that.
Here is the fixed controller :
/**
* #Route("admin/item/brand/editable-list", name="admin_item_brand_editable-list")
*/
public function editableList(FormFactoryInterface $formFactoryInterface, EntityManagerInterface $em, Request $request, BrandRepository $brandRepository)
{
$formHtml = [];
$brands = $brandRepository->findAll();
foreach ($brands as $brand) {
$form = $formFactoryInterface->createNamedBuilder($brand->getId(), BrandType::class, $brand)->getForm();
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->get('saveButton')->isClicked()) {
$em->flush();
$formHtml[] = $this->renderView('item/brand/_brandForm.html.twig', [
'formView' => $form->createView(),
'brandId' => $brand->getId(),
]);
} elseif ($form->get('deleteButton')->isClicked()) {
$em->remove($brand);
$em->flush();
} else {
throw new ErrorException('un bouton doit être clické');
}
} else {
$formHtml[] = $this->renderView('item/brand/_brandForm.html.twig', [
'formView' => $form->createView(),
'brandId' => $brand->getId(),
]);
}
}
return $this->render('item/brand/listForm.html.twig', [
'forms' => $formHtml,
]);
}
I try to render the collection type prototype I create with an embed collection form.
I read the documentation on Symonfy, Github, ... but don't succeed to understand the way to use the block to render the form.
Here I have a form (RegistrationFormType) based on the User entity which has an embed collection form of Adress (AdressFormType).
I succeed to add the button and generate new adress on the form but I would like to have my prototype with the same layout as the one of my first adress (retrieved from DB).
Could you help me to understand what I do wrong please?
Here my RegistrationFormType
<?php
namespace App\Form;
use App\Entity\User;
//use Doctrine\DBAL\Types\TextType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TelType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Form\CallbackTransformer;
class RegistrationFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('roles',ChoiceType::class,[
'choices'=>[
'Specialist'=>'Role_Specialist',
'Parent'=>'Role_Parent',
'Center'=>'Role_Center',],
'label'=>"Je m'inscris en tant que"])
->add('name')
->add('firstname',TextType::class, [
'label' => 'Firstname',
'row_attr' => [
'id' => 'firstname'
],])
->add('email')
->add('phone',TelType::class)
->add('NISS',TextType::class, [
'label' => 'NISS',
'row_attr' => [
'id' => 'NISS'
]
,
'required'=>'false',
])
->add('BCE',TextType::class, [
'label' => 'BCE',
'row_attr' => [
'id' => 'BCE'
],
'required'=>'false'])
->add('agreeTerms', CheckboxType::class, [
'mapped' => false,
'constraints' => [
new IsTrue([
'message' => 'You should agree to our terms.',
]),
],
])
->add('plainPassword', PasswordType::class, [
// instead of being set onto the object directly,
// this is read and encoded in the controller
'mapped' => false,
'attr' => ['autocomplete' => 'new-password'],
'constraints' => [
new NotBlank([
'message' => 'Please enter a password',
]),
new Length([
'min' => 6,
'minMessage' => 'Your password should be at least {{ limit }} characters',
// max length allowed by Symfony for security reasons
'max' => 4096,
]),
],
])
//imbrication de adress dans le formulaire user afin de retrouver toutes les adresses qui lui sont référées
->add('adress',CollectionType::class,[
'entry_type' => AdressType::class,
'entry_options' => ['label' => false],
'allow_add' => true,
'block_name' => 'adress'
])
;
// Data transformer
$builder->get('roles')
->addModelTransformer(new CallbackTransformer(
function ($rolesArray) {
// transform the array to a string
return count($rolesArray)? $rolesArray[0]: null;
},
function ($rolesString) {
// transform the string back to an array
return [$rolesString];
}
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
AdressType
<?php
namespace App\Form;
use App\Entity\Adress;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AdressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('type',ChoiceType::class,[
'choices' =>[
'Adresse Principale' => 'Principale',
'Adresse Secondaire' => 'Secondaire'
]
])
->add('housenumber',TextType::class,[
'label'=>'N°'
])
->add('additional_info',TextType::class,[
'label'=>'Apt/Etage/...',
'required'=>false
])
->add('street', TextType::class, [
'label' => 'Rue',
'row_attr' => [
'id' => 'Adress2'
],])
->add('postalcode')
->add('city')
->add('region')
->add('country')
->add('latitude', HiddenType::class)
->add('longitude', HiddenType::class)
// ->add('users')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Adress::class,
]);
}
}
The twig template
{% extends 'base.html.twig' %}
{% block title %}Register{% endblock %}
{% block body %}
{% for flashError in app.flashes('verify_email_error') %}
<div class="alert alert-danger" role="alert">{{ flashError }}</div>
{% endfor %}
<div class="container">
{{ form_start(registrationForm) }}
<div class="form-group">{{ form_row(registrationForm.roles) }}</div>
<div class="form-row">
<div class="form-group col-md-6">{{ form_row(registrationForm.name) }}</div>
<div class="form-group col-md-6">{{ form_row(registrationForm.firstname) }}</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">{{ form_row(registrationForm.email) }}</div>
<div class="form-group col-md-6">{{ form_row(registrationForm.plainPassword, {
label: 'Password'
}) }}</div>
</div>
<div class="form-row">
<div class="form-group col-md-4">{{ form_row(registrationForm.phone) }}</div>
<div class="form-group col-md-4">{{ form_row(registrationForm.NISS, {label: 'NISS'}) }}</div>
<div class="form-group col-md-4">{{ form_row(registrationForm.BCE, {label: 'BCE'}) }}</div>
</div>
{# #TODO formatter pour qu'on differencie bien les adresses entre elles par block. Cf block en dessous#}
<h3>Adresses</h3>
{% block _registration_form_adress_entry_widget %}
<div class="adress" data-prototype="{{ form_widget(registrationForm.adress.vars.prototype)|e('html_attr') }}">
{% for adress in registrationForm.adress %}
<div class="form-group col-md-4">{{ form_row(adress.type) }}</div>
<div class="form-row">
<div class="form-group col-md-4">{{ form_row(adress.street) }}</div>
<div class="form-group col-md-4">{{ form_row(adress.housenumber) }}</div>
<div class="form-group col-md-4">{{ form_row(adress.additional_info) }}</div>
</div>
<div class="form-row">
<div class="form-group col-md-3">{{ form_row(adress.postalcode) }}</div>
<div class="form-group col-md-3">{{ form_row(adress.city) }}</div>
<div class="form-group col-md-3">{{ form_row(adress.region) }}</div>
<div class="form-group col-md-3">{{ form_row(adress.country) }}</div>
</div>
{% endfor %}
</div>
<button type="button" class="add_item_link" data-collection-holder-class="adress">Add an adress</button>
{{ form_end(registrationForm) }}
{% endblock %}
</div>
<script>
const addFormToCollection = (e) => {
const collectionHolder = document.querySelector('.' + e.currentTarget.dataset.collectionHolderClass);
const item = document.createElement('li');
item.innerHTML = collectionHolder
.dataset
.prototype
.replace(
/__name__/g,
collectionHolder.dataset.index
);
collectionHolder.appendChild(item);
collectionHolder.dataset.index++;
};
document
.querySelectorAll('.add_item_link')
.forEach(btn => btn.addEventListener("click", addFormToCollection));
</script>
{% endblock %}
{#{% block registration_form_adress_entry_row %}#}
{# <div class="form-row">#}
{# <div class="form-group col-md-4">{{ form_row(adress.street) }}</div>#}
{# <div class="form-group col-md-4">{{ form_row(adress.housenumber) }}</div>#}
{# <div class="form-group col-md-4">{{ form_row(adress.additional_info) }}</div>#}
{# </div>#}
{# <div class="form-row">#}
{# <div class="form-group col-md-3">{{ form_row(adress.postalcode) }}</div>#}
{# <div class="form-group col-md-3">{{ form_row(adress.city) }}</div>#}
{# <div class="form-group col-md-3">{{ form_row(adress.region) }}</div>#}
{# <div class="form-group col-md-3">{{ form_row(adress.country) }}</div>#}
{# </div>#}
{#{% endblock %}#}
The code rendering
Thank you :)
You can define a macro that will render both the existing subfields of the form and the prototype string.
{% import _self as formMacros %}
{% macro address(item) %}
... your code formatting the address subform ...
{% endmacro %}
So this line in twig:
<div class="adress" data-prototype="{{ form_widget(registrationForm.adress.vars.prototype)|e('html_attr') }}">
would be
<div class="adress" data-prototype="{{ formMacros.address(registrationForm.adress.vars.prototype)|e('html_attr') }}">
and same thing for the existing fields.
I have a page with forms in hiddens modals.
Forms come from the same entity with different ids.
Displaying the modal works. For each modal I want to display, datas are ok inside inputs.
The issue is : when I submit the form, every forms (hidden included) are persisted.
//EditServiceType.php
namespace Guillaume\PartnerManagerBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class EditServiceType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', null, array(
'label_attr' => array('class' => 'col-form-label'),
'attr' => array('class' => 'form-control')
))
->add('type')
->add('version')
->add('connection_type', ChoiceType::class, array(
'choices' => array(
'Connected' => 2,
'Local' => 1,
)));
}/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Guillaume\PartnerManagerBundle\Entity\Service'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'edit_guillaume_partnermanagerbundle_service';
}
}
Part of my Controller
$formEdits = [];
$forms = [];
$serviceFormEdits = [];
foreach($services as $service) {
$serviceFormEdits[$service->getId()] = $em->getRepository('GuillaumePartnerManagerBundle:Service')->find($service);
$forms[$service->getId()] = $this->createForm('Guillaume\PartnerManagerBundle\Form\EditServiceType', $serviceFormEdits[$service->getId()]);
$formEdits[$service->getId()] = $forms[$service->getId()]->createView();
$forms[$service->getId()]->handleRequest($request);
if ($forms[$service->getId()]->isSubmitted() && $forms[$service->getId()]->isValid()) {
$em->persist($serviceFormEdits[$service->getId()]);
$em->flush();
$this->addFlash('notice', 'Service has been edited');
}
}
}
//(...)
return $this->render('GuillaumePartnerManagerBundle:customers:customer.html.twig', [
'formEdits' => $formEdits,
]);
Part of my twig (the modal)
{% for result in results %}
{% form_theme formEdits[result.service.id] 'bootstrap_4_horizontal_layout.html.twig' %}
<div class="modal fade" id="editEnvironment-{{ result.service.id }}" tabindex="-1" role="dialog"
aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="exampleModalLongTitle">{{ 'Edit Environment'|trans }}</h2>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{{ form_start(formEdits[result.service.id]) }}
<div class="form-group row">
{{ form_widget(formEdits[result.service.id]) }}
</div>
<div class="modal-footer row">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" value="cancel" class="btn btn-secondary" data-dismiss="modal">{{ 'Cancel'|trans }}</button>
<button type="submit" value="save" class="btn btn-primary">{{ 'Validate'|trans }}</button>
</div>
</div>
{{ form_end(formEdits[result.service.id]) }}
</div>
</div>
</div>
</div>
{% endfor %}
Finally I figured it out.
adding 'id' in options resolver
$forms[$service->getId()] = $this->createForm('Guillaume\PartnerManagerBundle\Form\EditServiceType', $serviceFormEdits[$service->getId()], ['id' => $service->getId()]);
adding input hidden in formType
->add('id', HiddenType::class, array(
'data' => $options['id'],
'mapped' => false,
))
and I use this id when submit is valid
$postData = $request->request->get('edit_guillaume_partnermanagerbundle_service');
$postId = $postData['id'];
$forms[$postId]->handleRequest($request);
if ($forms[$postId]->isSubmitted() && $forms[$postId]->isValid()) {
$em->persist($serviceFormEdits[$postId]);
$em->flush($serviceFormEdits[$postId]);
//(...)
Any idea how to solve the following approach.
I have a form and want to display the entered data in a specific formtemplate before store it in the DB. If the entered data looks properly, the user can save the form.So I am searching for a way to display the entered data as a preview in a new window/tab first. With my code below I am not able to preview the form without saving the data in the databse. Also display the preview in a new window or tab is not possible. I guess there is no way to achieve this with php / laravel. I tried some onlick events, but no luck. As it seems like the route is prefered.
Any idea how to solve this?
My form looks like:
{{ Form::open(array('url' => 'backend/menubuilder/'.$id, 'method' => 'PUT'))}}
<section>
<div class="container">
<div class="row">
<div class="inputBox">
<div class="col-xs-12 col-md-6">
<h3>Montag</h3>
<div class="form-group">
{{Form::label('gericht_1_mo','Gericht 1')}}
{{Form::textarea('gericht_1_mo', Auth::user()->gericht_1_mo,array('class' => 'form-control'))}}
</div>
<div class="form-group">
{{Form::label('preis_1_mo','Preis', array('class' => 'col-md-6'))}}
{{Form::text('preis_1_mo', Auth::user()->preis_1_mo, array('class' => 'col-md-6'))}}
</div>
<div class="form-group mrgT55">
{{Form::label('gericht_2_mo','Gericht 2')}}
{{Form::textarea('gericht_2_mo', Auth::user()->gericht_2_mo,array('class' => 'form-control'))}}
</div>
<div class="form-group">
{{Form::label('preis_2_mo','Preis', array('class' => 'col-md-6'))}}
{{Form::text('preis_2_mo', Auth::user()->preis_2_mo, array('class' => 'col-md-6'))}}
</div>
</div>
</div>
</div>
</div>
</div>
{{Form::submit('update')}}
{{-- <input type="submit" name="preview" value="preview"> --}}
{{Form::close()}}
{{ Form::open(array('url' => 'backend/menubuilder/templatesview/'.$id, 'method' => 'POST'))}}
{{-- {{Form::submit('Preview',array('onClick' => 'target_blank'))}} --}}
<input onclick="newTab()" type="submit" name="preview" value="preview" >
{{Form::close()}}
My routes:
Route::get('backend/menubuilder/templates/{id}', 'MenuBuilderController#template');
Route::post('backend/menubuilder/templatesview/{id}', 'MenuBuilderController#preview');
My Controller:
public function preview($id)
{
$user = User::find($id);
$owner = (Auth::id() === (int) $id);
return View::make('backend/menubuilder/templatesview/tempone')->withUser($user)->withOwner($owner);
}
public function template($id)
{
$user = User::find($id);
$owner = (Auth::id() === (int) $id);
return View::make('backend/menubuilder/templates/tempone')->withUser($user)->withOwner($owner);
}
i need to render 2 forms on the same page. To do this, I have 2 actions in my controller, the first one manage the form 1 and render the entire page, the second manage the form 2 and render only this form.
The second action is called in twig with a :
{% render (controller("AppBundle:User:secondForm")) %}
Both are rendered, both work, excepted when the validation of the form 2 fail. The Controller return the user to the form with form errors but instead of returning to the entire page, it only render the form.
My code look like this :
First action:
/**
* #Route("/profile/global-page", name="global_page")
*/
public function Global1Action(Request $request)
{
[.......]
$process = $formHandler->process($user);
if ($process) {
$request->getSession()->getFlashBag()->add('success', 'ok');
return $this->redirect($this->generateUrl('an_url'));
}
return $this->render('entire_page.html.twig', array(
'form' => $form->createView(),
));
}
then Twig global (entire_page.html.twig):
{% extends 'base.html.twig' %}
{% block content %}
{#FlashBags#}
{% include 'components/alert.html.twig' with {'type':'success'} %}
<div class="col-md-offset-3 col-md-6">
<div class="col-md-12 row">
<div class="panel panel-profil">
<div class="panel-heading">
<h3 class="panel-title">form 1</h3>
</div>
<div class="panel-body">
<form action="{{ path('global_page') }}" method="POST" class="form-horizontal text-center">
{{ form_widget(form) }}
<button type="submit" name="submit" class="btn btn-main button-sm">Go</button>
</form>
</div>
</div>
</div>
</div>
{% render (controller("AppBundle:User:secondForm")) %}
{% endblock %}
then SecondForm action:
/**
* #Route("/profile/second-form", name="second_form")
*/
public function secondFormAction(Request $request)
{
[.......]
$process = $formHandler->process($user);
if ($process) {
$request->getSession()->getFlashBag()->add('success', 'ok');
return $this->redirect($this->generateUrl('an_url'));
}
return $this->render('only_form2.html.twig', array(
'form' => $form->createView(),
));
}
and finaly the second twig (only_form2.html.twig):
<div class="col-md-offset-3 col-md-6">
<div class="col-md-12 row">
<div class="panel panel-profil" style="margin-top: 10px;">
<div class="panel-heading">
<h3 class="panel-title"> second form panel </h3>
</div>
<div class="panel-body">
<form action="{{ path('second_form') }}" {{ form_enctype(form) }} method="POST">
{{ form_widget(form) }}
<button type="submit" name="submit" class="btn btn-main button-sm">Go 2</button>
</form>
</div>
</div>
</div>
I don't understand how to return the user to the entire page (with form errors) instead of rendering only the second form when it's validation fail.
Thank you !
Edit: I found this post which explain how to have 2 forms in one controller. Answer below seems to not work with Symfony 2.8
You can use a multi form action. Something like this :
public function multiformAction()
{
$form1 = $this->get('form.factory')->createNamedBuilder($formTypeA, 'form1name')
->add('foo', 'text')
->getForm();
$form2 = $this->get('form.factory')->createNamedBuilder($formTypeB, 'form2name')
->add('bar', 'text')
->getForm();
if('POST' === $request->getMethod()) {
if ($request->request->has('form1name') {
// handle the first form
}
if ($request->request->has('form2name') {
// handle the second form
}
}
return array(
'form1' => $form1->createView(),
'form2' => $form2->createView()
);
}
See this post. And this question
To solve this issue you need to send Form request to action where render whole page (Global1Action). Not to action where second form is created.
You will need also move both forms handling to Global1Action.
To change second form action use this method:
$form->setAction($this->generateUrl('global_page'))
Or you can implement ajax handling for second form (if you need to keep it's logic in separate action).