web-dev-qa-db-ja.com

symfonyでのajax呼び出しからのフォーム検証

ブラウザを更新しないようにajaxを呼び出して、symfonyのフォームからデータを保存する必要があります。また、フィールドでエラーが発生した場合、Ajaxの呼び出しに応答してエラーを取得し、ページを更新せずにフォームエラーを表示する必要があります。

フィールドを検証し、ajax呼び出しが実行され、データを保存するか、エラーを表示するページを更新する場合、すべてを完璧にするフォームをsymfonyアセットで持っていますが、ページを更新せずに同じものを必要としています。

次に、使用しているコードの一部を配置します。

コントローラ:

public function createAction(Request $request)
{
    $entity = new Student();
    $form = $this->createCreateForm($entity);
    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($entity);
        $em->flush();

        return $this->redirect($this->generateUrl('student_show', array('id' => $entity->getId())));
    }

    return $this->render('BackendBundle:Student:new.html.twig', array(
        'entity' => $entity,
        'form'   => $form->createView(),
    ));
}

ajax call:(エラー部分の処理方法がわかりません)

$('.form_student').submit(function(event) {
   event.preventDefault();

  $.ajax({
    type: 'POST',
    url: Routing.generate('student_create'),
    data: $(this).serialize(),

    success: function(data) {

      //clean form
      cleanForm($(this));

      //show success message
      $('#result').html("<div id='message'></div>");
      $('#message').html("<h2> student created</h2>").hide();
      $('#message').fadeIn('slow').delay(5000).fadeOut('slow');
      event.stopPropagation();   
    },
    error: function (xhr, desc, err) 
      {
        alert("error");
      }
    })
  return false;
});

コントローラーからJsonResponseを返し、Ajaxを使用するものを見たことがありますが、Ajaxから始めて、それを使用する方法がわかりません。それから私は私が意味するコードを入れます:

 if ( $request->isXmlHttpRequest() ) {

    if ($form->isValid()) {
     //...
     return new JsonResponse(array('message' => 'Success!'), 200);
    }

    $response = new JsonResponse(array(
    'message' => 'Error',
    'form' => $this->renderView('BackendBundle:student:new.html.twig',
            array(
        'entity' => $entity,
        'form' => $form->createView(),
    ))), 400);

  return $response;
}

Ajaxを使用してこの問題を解決する方法をもっと理解してもらえれば、永遠に感謝します。私が見た多くのマニュアルでは、まだよく理解していないからです。

事前にどうもありがとうございました。

13
Joseph

Ajax呼び出しで送信されたフォームのエラーを管理するために、古いプロジェクトで使用しているカスタムソリューションを共有できます。

コントローラーアクション:

 ....
 if ( $request->isXmlHttpRequest() ) {

        if (!$form->isValid()) {
                return array(
            'result' => 0,
            'message' => 'Invalid form',
            'data' => $this->getErrorMessages($form)
        );

            // Do some stuff
           return array(
            'result' => 1,
            'message' => 'ok',
            'data' => ''
         }

}
    // Generate an array contains a key -> value with the errors where the key is the name of the form field
    protected function getErrorMessages(\Symfony\Component\Form\Form $form) 
    {
        $errors = array();

        foreach ($form->getErrors() as $key => $error) {
            $errors[] = $error->getMessage();
        }

        foreach ($form->all() as $child) {
            if (!$child->isValid()) {
                $errors[$child->getName()] = $this->getErrorMessages($child);
            }
        }

        return $errors;
    }

そしてjsコードは次のようなものです:クライアント側:

        $.ajax({
            url: ...,
            data: ....,
            type: "POST",
            success: function(data) {
                if(data.result == 0) {
                    for (var key in data.data) {
                        $(form.find('[name*="'+key+'"]')[0]).before('<ul class="errors"><li>'+data.data[key]+'</li></ul>');
                    }
                } else {
                // Submit OK
                }
            }
        });

この助けを願っています

19
Matteo

実際には、ajax経由でフォームを送信するときにフォーム検証エラーをレンダリングするはるかに簡単な方法があります。上記のどちらの回答でも、エラーメッセージを正しいフィールドなどに手動で添付する必要があります。

質問が古いので、ここで同様の問題を抱えて来た人のために、あなたの特定のケースから少し一般化します:

コントローラーでは、検証されない場合はレンダリングされたフォームを返すだけです。

public function createAction(Request $request)
{
    $form = $this->createForm(StudentType::class);
    $form->handleRequest($request);

    if ($form->isSubmitted() && !$form->isValid()) {
        return $this->render('new.html.twig', [
            'form' => $form->createView(),
        ]);
    }
    // ...
}

次に、ajax呼び出しで、返されたhtml(検証エラーメッセージを含む)を取得して、フォームにプラグインします。以下では、フォームのコンテンツのみを置き換えているため、フォーム自体にアタッチされているハンドラーはそのまま残ります。

$.ajax({
    url: ...,
    data: ....,
    type: "POST",
    success: function(data) {
        if(!data.success) { // undefined here, set to true in controller the form is valid
            var innerHTML = $(data).find('#appbundle_student').html();
            $('#appbundle_student').html(innerHTML);
        } else {
            // Submit OK
        }
    }
});
5
SimonW

Symfony 3とエラーバリデーターを使用すると、次のようにAjaxリクエストを解析できます:

 /**
     * Create new student (ajax call)
     * @Method("POST")
     * @Route("/student/create", name"student_create")
     * @param Request $request
     * @return JsonResponse
     */
    public function createAction(Request $request)
    {

        $student = new Student();
        $form = $this->createForm(CreateStudentType::class, $student);
        $form->handleRequest($request);
        $errors = array();

        if ($form->isSubmitted()) {
            $validator = $this->get('validator');
            $errorsValidator = $validator->validate($student);

            foreach ($errorsValidator as $error) {
                array_Push($errors, $error->getMessage());
            }


            if (count($errors) == 0) {
                $em = $this->getDoctrine()->getManager();
                $em->persist($student);
                $em->flush();

                return new JsonResponse(array(
                    'code' => 200,
                    'message' => 'student toegevoegd',
                    'errors' => array('errors' => array(''))),
                    200);
            }

        }

        return new JsonResponse(array(
            'code' => 400,
            'message' => 'error',
            'errors' => array('errors' => $errors)),
            400);
    }

そしてjquery ajax

$("#createForm").submit(function(e) {

        e.preventDefault();
        var formSerialize = $(this).serialize();

        var url = location.Origin + '/web/app_dev.php/student/create';
        $.ajax({
            type: "POST",
            url: url,
            data: formSerialize,
            success: function (result) {
                console.log(result);
                if (result.code === 200) {
                    // refresh current url to see student
                } else {

                }
            }
        });
    });
2
Vince Verhoeven