Form Validation in symfony from ajax call
I can share with you a custom solution i use in an old project for manage error on form submitted via ajax call.
In the controller action:
.... 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; }
And the js code is something like:In the client side:
$.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 } } });
hope this help
There is actually a much easier way to render form validation errors when submitting a form via ajax. Both the answers above require you to manually attach the error messages to the right fields, etc.
Since the question is old, I will generalize a bit from your specific case for those who come here with a similar problem:
In the controller, you can just return the rendered form if it does not validate:
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(), ]); } // ...}
Then in your ajax call, you can take the html that gets returned (including any validation error messages) and plug it back into your form. Below I replace just the contents of the form, so any handlers attached to the form itself stay intact.
$.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 } }});
With symfony 3 and the error validator you can parse your Ajax request like this:
/** * 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); }
And 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 { } } }); });