I need to store data from a form with symfony through an ajax call me not to update the browser. Also I need you in case of errors in the fields can somehow get them in resp
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 {
}
}
});
});
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
}
}
});
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