web-dev-qa-db-fra.com

Symfony2: deux formulaires sur une même page

J'ai deux formulaires sur une même page.

Mon problème est que lorsque j'ai essayé de soumettre un formulaire, c'est comme s'il essayait de soumettre également le deuxième formulaire ci-dessous dans la page.

Comme suit, vous pouvez retrouver mes 2 formulaires:

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();
}

Mon deuxième formulaire comme seulement un bouton d'envoi.

Je les ai passés à mon rendu et les ai affichés en utilisant:

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

"formulaire" est le nom de ma variable pour le premier formulaire et "mise à jour" pour mon deuxième formulaire.

Lorsque j'ai tenté de soumettre mon deuxième formulaire, je dois cliquer deux fois et finalement j'obtiens:

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

J'ai essayé d'ajouter validation_group à false mais en vain.

Je ne comprends pas pourquoi j'ai eu cette erreur car mes formulaires ne sont pas du tout intégrés

J'espère que vous comprendrez...

20
scamp

Vous devez traiter les formulaires séparément:

if('POST' === $request->getMethod()) {

    if ($request->request->has('form1name')) {
        // handle the first form  
    }

    if ($request->request->has('form2name')) {
        // handle the second form  
    }
}

Ceci est parfaitement expliqué dans Symfony2 Multiple Forms: Différent des Embedded Forms

24
Mick

Cela a fait l'affaire pour moi dans Symfony 3 (devrait également fonctionner pour 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
    }

}
11
totas

Le problème est que vous avez deux formulaires sans nom (entrez des noms comme inputname au lieu de formname[inputname], et donc lorsque vous liez la demande à votre formulaire et qu'elle est validée, elle détecte certains champs supplémentaires (l'autre formulaire) et donc elle n'est pas valide.

La solution à court terme consiste à créer un générateur nommé via la fabrique de formulaires, donc au lieu de:

$form = $this->createFormBuilder(null)

tu devrais utiliser:

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

La solution à long terme serait de créer vos propres classes de formulaire , de cette façon, vous pouvez garder votre code de formulaire séparé du contrôleur.

7
Maerlyn

Les deux formulaires seront affichés.

Essayez d'utiliser:

    $this->createNamedBuilder 

au lieu de

    $this->createFormBuilder

Ensuite, dans votre contrôleur, recherchez le formulaire par son nom:

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

Voici comment je les gère sur mon contrôleur:

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

Voici le html du second formulaire:

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

Voici mon twig rendu:

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

J'espère que cela t'aidera.

1
scamp

L'utilisation de formulaires nommés est une solution viable pour gérer plusieurs formulaires, mais cela peut devenir un peu compliqué, en particulier si vous générez des formulaires de manière dynamique.

Une autre méthode, à partir de Symfony 2.3, consiste à vérifier quel bouton de soumission a été cliqué.

Par exemple, en supposant que chaque formulaire possède un bouton d'envoi nommé '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
    }
}

Je pense que cela a une petite quantité de frais supplémentaires par rapport à la méthode du générateur nommé (en raison de plusieurs appels handleRequest), mais, dans certains cas, cela entraîne un code plus propre. Toujours bon d'avoir plusieurs solutions au choix. Une partie de la surcharge supplémentaire pourrait être allégée via des instructions imbriquées if/else, si nécessaire, mais, à moins que nous parlions de dizaines de formulaires par page, la surcharge supplémentaire est de toute façon négligeable.

Voici une implémentation alternative utilisant des fonctions anonymes qui minimise la répétition du code:

$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);
        }
    }
}
1
Kal Zekdor