web-dev-qa-db-ja.com

Symfony2:同じページの2つのフォーム

同じページに2つのフォームがあります。

私の問題は、フォームを送信しようとしたときに、ページの下にある2番目のフォームも送信しようとしたことです。

次のように、あなたは私の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();
}

送信ボタンとしてのみの2番目のフォーム。

それらをレンダーに渡し、以下を使用して表示します。

<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」は最初のフォームの変数名、2番目のフォームの「update」です。

2番目のフォームを送信しようとすると、2回クリックする必要があり、最終的に次のようになります。

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

Validation_groupをfalseに追加しようとしましたが、役に立ちませんでした。

フォームがまったく埋め込まれていないため、このエラーが発生した理由がわかりません

あなたが理解することを願っています...

20
scamp

フォームを個別に処理する必要があります。

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

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

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

これは Symfony2の複数のフォーム:埋め込みフォームとは異なる で完全に説明されています

24
Mick

これは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
    }

}
11
totas

問題は、2つの名前のないフォーム(formname[inputname]の代わりにinputnameのような入力名があるため、リクエストをフォームにバインドして検証すると、いくつかの余分なフィールドを検出することです(他のフォーム)そしてそれは無効です。

短期的な解決策は、フォームファクトリを介して名前付きビルダーを作成することです。

$form = $this->createFormBuilder(null)

あなたが使用する必要があります:

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

長期的な解決策は、 独自のフォームクラスを作成する です。これにより、フォームコードをコントローラーとは別に保つことができます。

7
Maerlyn

2つのフォームが投稿されます。

使用してみてください:

    $this->createNamedBuilder 

の代わりに

    $this->createFormBuilder

次に、コントローラーで、名前でフォームを見つけます。

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

これは私がコントローラーでそれらを処理する方法です:

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

これは、2番目のフォームの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>

これは私のtwig rendered:

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

これがお役に立てば幸いです。

1
scamp

名前付きフォームの使用は、複数のフォームを処理するための実行可能なソリューションですが、特にフォームを動的に生成する場合は、少し面倒になります。

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

これは、名前付きビルダーメソッド(複数の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);
        }
    }
}
1
Kal Zekdor