Making Ajax calls is a trivial task nowadays for any web developer, and I’m sure it’s no enigma for all of you how to do it using your favourite Javascript library or framework like jQuery, Angular, Backbone, you name it.
Forms and ajax
But how do we handle these requests in the backend? More specifically, how should we write our controllers to take full advantage of our preferred framework, Symfony 2 in my case, and create a great UX for our consumers (with errors displayed nicely and effortless) and a great feeling for our colleagues with whom we share the code (by using status codes and promises).
Firstly I prepare a basic controller, while trying to respect REST principles. This will prove very valuable later on in the project and your app flow will be easier to follow. A good article on that can be found here .
/Acme/DemoBundle/Controller/DemoController.php
[...] use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; [...] /** * Renders the "new" form * * @Route("/", "demo_new") * @Method("GET") */ public function newAction(Request $request) { $entity = new Demo(); $form = $this->createCreateForm($entity); return $this->render('AcmeDemoBundle:Demo:new.html.twig', array( 'entity' => $entity, 'form' => $form->createView() ) ); } /** * Creates a new Demo entity. * * @Route("/", name="demo_create") * @Method("POST") * */ public function createAction(Request $request) { //This is optional. Do not do this check if you want to call the same action using a regular request. if (!$request->isXmlHttpRequest()) { return new JsonResponse(array('message' => 'You can access this only using Ajax!'), 400); } $entity = new Demo(); $form = $this->createCreateForm($entity); $form->handleRequest($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($entity); $em->flush(); return new JsonResponse(array('message' => 'Success!'), 200); } $response = new JsonResponse( array( 'message' => 'Error', 'form' => $this->renderView('AcmeDemoBundle:Demo:form.html.twig', array( 'entity' => $entity, 'form' => $form->createView(), ))), 400); return $response; } /** * Creates a form to create a Demo entity. * * @param Demo $entity The entity * * @return SymfonyComponentFormForm The form */ private function createCreateForm(Demo $entity) { $form = $this->createForm(new DemoType(), $entity, array( 'action' => $this->generateUrl('demo_create'), 'method' => 'POST', )); return $form; }
Then I prepare my HTML:
/Acme/DemoBundle/Resources/Demo/new.html.twig
{% block body -%} <h1>Demo creation</h1> <div class="form_error"></div> <form method="POST" class="ajaxForm" action="{{path('demo_create')}}" {{ form_enctype(form) }}> <div id="form_body"> {% include 'AcmeDemoBundle:Demo:form.html.twig' with {'form': form} %} </div> <button type="submit" class="btn btn-primary">Submit</button> {{form_rest(form)}} </form> <ul class="record_actions"> <li> <a href="{{ path('demo') }}"> Back to the list </a> </li> </ul> {% endblock %} {% block javascripts %} <script> initAjaxForm(); </script> {% endblock %}
And then I build the form; It’s always a good practice to put the fields of your form in a separate file so that you can reuse them for the edit form for example.
/Acme/DemoBundle/Resources/Demo/form.html.twig
<div class="row" > <div class="col-lg-4 col-md-4"> <div class="col-md-12">{{ form_errors(form) }}</div> <div class="bg-danger">{{ form_errors(form.name) }}</div> <div class="form-group input-group"> {{ form_widget(form.name, {'attr': {'placeholder':'Name', 'title':'Name', 'class':'form-control'}}) }} </div> </div> <div class="col-md-4"> <div class="bg-danger">{{ form_errors(form.isActive) }}</div> <div class="form-group"> {{ form_widget(form.isActive, {'attr': {'title':'Is active', 'class':'form-control'}}) }} </div> </div> </div>
And to tie the frontend with the backend we add a little Javascript (JQuery flavoured). This code simply listens to all submits from the page, and if the submitted form has the class ajaxForm then it submits it using Ajax.
Thanks to the handy promises .done
and .fail
, and to the use of status codes in our response (400 -> Bad request, 200 -> Ok, 404 -> Not Found and so on) the script will automatically go to the right promise and will make handling the response a lot easier. Also, if an error occurs in your form (e.g. a field is invalid), then the form is re-rendered with the errors displayed.
/Acme/DemoBundle/Resources/public/main.js
function initAjaxForm() { $('body').on('submit', '.ajaxForm', function (e) { e.preventDefault(); $.ajax({ type: $(this).attr('method'), url: $(this).attr('action'), data: $(this).serialize() }) .done(function (data) { if (typeof data.message !== 'undefined') { alert(data.message); } }) .fail(function (jqXHR, textStatus, errorThrown) { if (typeof jqXHR.responseJSON !== 'undefined') { if (jqXHR.responseJSON.hasOwnProperty('form')) { $('#form_body').html(jqXHR.responseJSON.form); } $('.form_error').html(jqXHR.responseJSON.message); } else { alert(errorThrown); } }); }); }
Going a little further, you could put this form in a modal (easily done with bootstrap) and you can get a really nice user interface with forms in modals submitted with Ajax.
Last but not least, don’t forget to check that your routings are correct in case you didn’t do it already:
app/config/routing.yml
demo: resource: "@AcmeDemoBundle/Controller/" type: annotation prefix: /
Have fun coding 🙂
Thanks for helping me to implement ajax validation in 5 minutes 🙂
Hey Johnathan,
It has been a pleasure.
If you use AngularJS for Ajax, there is nothing like:
e.preventDefault();
So to prevent the form from effectively being submitted, you have to get rid of the form’s “action” attribute – which is not so easy, see http://stackoverflow.com/questions/28499529/angularjs-and-symfony2-forms-or-how-to-remove-forms-action-attribute
Hi,
Have you the full source of code, I get always a problem (you can access this only ajax) and when i delete it, I don’t get the result.
Thanks for help
Regards for helping out, superb information. ccekbaedggdg
Hi, thank you so much, I did try and change a little bit your code until I get a 500 error (seen using firebug) and the sf2 error recommand to add the following use statement “Symfony\Component\HttpFoundation\JsonResponse;” in my controller… to get a 200 success response. Hoping I will help someone, one day !
I’m getting this error:
Recursion detected (500 Internal Server Error)
Any idea what could it be?
Thank you
Hi all,
I’m trying to implement this in my “hybrid system” (a different framework that makes use of symfony forms), the solution works the first time I get an error, the form is re-rendered and the error shown, but when I submit the form again it seems the form.submit event is not triggered (the default event is not prevented and the action url loaded) so I miss the ajax functionality.
Inspecting further, I noticed that when the form fails, in the console I get an error POST … 400 (bad request) which I return in the JSONResponse. Can it prevent the js to execute? How to solve it?
Nice blog here! Also your site loads up very fast! What host are you using?
Can I get your associate hyperlink to your host? I desire my site loaded up as quickly as yours lol
What if you close the modal window and open it again you will have 2 objects that will be sent to the database…
Hi Dan, opening a modal should not send any data to the database. Only submitting the form.
bonjour , je cherche une solution upload des fichiers avec jquery ,ajax en symfony 2 et merci d avance
My brother suggested I would possibly like this web site.
He was totally right. This publish actually made my day.
You can not imagine simply how so much time I had spent for this info!
Thank you!
I like all your posts. You’ve done fantastic job
Many thanks for helping people find the information they need. Great stuff as always. Keep up the good work!!!
https://ngote.000webhostapp.com/blog/write-my-essay-or-paper-for-me/
http://www.supportsoft.com.au/do-my-homework-for-me-homework-aid-on-homework-20/
Whoa! This can be by far the most useful thing on the topic I have ever read. Thanks for your work.
http://domusgmt.ro/post/9725
It is my first time visiting your website and I’m very interested. Many thanks for sharing and keep up 😉
http://pandoracompany.org/?p=565
it’s a really great site!A lot of helpful information and handy tips, thank you =)
http://sociologyessay38.host-sc.com/2018/02/08/professional-essay-will-help-you-to-succeed-in-the-education/
Awesome! This may be one of the most helpful things on the matter I’ve ever read. Thanks for your work.
http://www.ducadimorrone.com/2018/01/24/top-rated-ten-custom-essay-writing-services-ranked-2/
Amazing site, how do u get all this info?I’ve read through a few articles on your site and I love your writing style. Thanks a million, keep up the good work.
http://viprental.hu/2017/12/20/hints-about-how-a-great-secondary-education-school/
This is an amazing article. This site is loaded with lots of useful things, it made it easier for me in many ways.
http://cuteqip.net/online-made-to-order-coming-up-with-services/
I’ve seen something similar in a different thread. You can definitely find some parts of that post useful, not everything of course, but I think it is worth looking into.
http://www.blackplanet.com/your_page/blog/view_posting.html?pid=9510100&profile_id=104428356&profile_name=highschoolessays&user_id=104428356&username=highschoolessays
This is an excellent resource!A lot of useful info and handy suggestions, thanks a lot =)
http://bmlv2016.com/find-some-personalized-essay-writing-help-with-2/
Great post\Nice post, i like it very much.I was very lucky to discover your site. It’s got a lot of useful information!
http://essayforcollege32.blog2learn.com/10747331/tips-on-how-to-succeed-in-college
Great website, how do you find all this information?I have read through a couple of articles on your website and I like your writing style. Thanks a million, keep up the great work.
http://www.thingsyousawinamovie.com/information-on-admission-essay-55
it’s an excellent site!A lot of useful info and handy tips, thank you =)
http://nanonghehvqy.com/what-is-a-thesis/
Thanks for helping people find the info they need. Good stuff as usual. Keep up the great work!!!
http://creactive.med.ad.bgu.ac.il/study-report-writing-format-jobs-employment-6/
Good post, I enjoyed it very much.I was really lucky to find your site. There is a lot of helpful info!
http://lambrecht.eu/specialized-on-line-essay-or-dissertation-creating/
Wow! This may be one of the most helpful things on the subject I have ever come across. Many thanks for your effort.
https://diederichhenrvd124545588.kroogi.com/en/content/3502153-Same-day-essay-for-you.html
I glanced through this website and there’s so much handy information, bookmarked 🙂
http://musicessay26.iktogo.com/post/–how-to-get-an-ideal-admission–
Thank you for a really fantastic blog. It was actually very useful. I’m so glad I found this.
http://h0mepage.net/illustrativeessay/2018/02/08/your-professional-writing-service-number-1/
Wow! This could be one of the most helpful things on the subject I have ever come across. Many thanks for your effort.
http://meghandonahue.com/custom-paper-writing-solutions-119/