On certain pages I use forms within bootstrap modals. I submit the form with Ajax and it gets validated in the controller. The most users will fill in the form correctly but if a validation fails the form is re-rendered and got send back to the user. I don't like this at all, but I can't find a better way because I can't get access the validation errors of the fields. Does someone has a better approach to achieve validation errors send back in JSON?
-
You can make a validation in JS, but imho taht's better approach to do server side validation. Snding data via JSON is a good choice. What is wrong with this approach ?Pawel– Pawel2013-12-04 14:17:04 +00:00Commented Dec 4, 2013 at 14:17
-
1No, I don't use JS validation because I don't want to define validations on two seperate places. I do server side validation at the moment but I can't find a decent way to get all errors from the form + entity properties and validators.Pi Wi– Pi Wi2013-12-04 14:33:55 +00:00Commented Dec 4, 2013 at 14:33
-
Just interate over elements from the form, and get errors of each.Pawel– Pawel2013-12-04 14:44:02 +00:00Commented Dec 4, 2013 at 14:44
4 Answers
I created a function myself
public function getFormErrors(Form $form) {
$errors = $form->getErrors();
foreach ($form->all() as $child) {
foreach ($child->getErrors() as $key => $error) {
$template = $error->getMessageTemplate();
$parameters = $error->getMessageParameters();
foreach ($parameters as $var => $value) {
$template = str_replace($var, $value, $template);
}
$errors[$child->getName()][] = $template;
}
}
return $errors;
}
Comments
if I understand right you have a form and you need to get the errors for each field separately. if so, have a look at \Symfony\Component\Form\Form::getErrorsAsString() & do smth of the kind:
function getFormErrors($form)
{
$errors = array();
// get the form errors
foreach($form->getErrors() as $err)
{
// check if form is a root
if($form->isRoot())
$errors['__GLOBAL__'][] = $err->getMessage();
else
$errors[] = $err->getMessage();
}
// check if form has any children
if($form->count() > 0)
{
// get errors from form child
foreach ($form->getIterator() as $key => $child)
{
if($child_err = getFormErrors($child))
$errors[$key] = $child_err;
}
}
return $errors;
}
1 Comment
I'd say that the cleanest solution is to implement JMSSerializerBundle (http://jmsyst.com/bundles/JMSSerializerBundle) which uses the following Class:
then in your controller:
// ...
if ($request->isXMLHttpRequest()) {
$jsonResponse = new JsonResponse();
$serializer = $this->container->get('jms_serializer');
$form = $serializer->serialize($form, 'json');
$data = array('success' => false,
'errorList' => $form);
$jsonResponse->setData($data);
return $jsonResponse;
}
2 Comments
errorList field of the response. It means you have to JSON.parse a string that is contained in a JSON reponse...I just have the same problem Today !
I sent the form with ajax, and if my controller sent me not a json 'OK', the form is refresh with the new form sent by the controller, who contains errors. Data 'OK' is sent when form->isValid(), else it return the form render.
HTML :
<div class="form_area">
<form id="myform" action.... >
...code form ...
</form>
</div>
Controller Action:
use Symfony\Component\HttpFoundation\JsonResponse;
public function myEditAction(){
.......
if ( $request->getMethod() == 'POST' ) {
$form->bind($request);
if ($form->isValid()) {
... code whn valide ...
if ( $request->isXmlHttpRequest() ) {
return new JsonResponse('OK');
}
}
}
return $form;
}
JS:
$('#myform').on('submit',function(e){
var formdata = $('#myform').serialize();
var href = $(this).attr('action');
$.ajax({
type: "POST",
url: href,
data: formdata,
cache: false,
success: function(data){
if(data != "OK") {
$('.form_area').html(data);
}
},
error: function(){},
complete: function(){}
});
return false;
});