Submit symfony 3 form with ajax

I am trying to implement my symfony / modal forms with ajax to stop the page reloading every time I submit the add / remove and update action, but there is a problem that I am not familiar with ajax and I do not know how to do this. Can someone help me understand the concept.

mY entity:

<?php namespace EvalBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * Department * * @ORM\Table(name="department") * @ORM\Entity(repositoryClass="EvalBundle\Repository\DepartmentRepository") */ class Department { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string * * @ORM\Column(name="name", type="string",unique=true) */ private $name; /** * One Department has Many Collaborators. * @ORM\OneToMany(targetEntity="Collaborator", mappedBy="department") */ private $collaborators; /** * Get id * * @return int */ public function getId() { return $this->id; } /** * Set name * * @param string $name * * @return Department */ public function setName($name) { $this->name = $name; return $this; } /** * Get name * * @return string */ public function getName() { return $this->name; } } 

:

 <?php namespace EvalBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class DepartmentType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name'); } /** * {@inheritdoc} */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => 'EvalBundle\Entity\Department', 'attr' => array('novalidate' => 'novalidate') )); } /** * {@inheritdoc} */ public function getBlockPrefix() { return 'evalbundle_department'; } } 

Controller:

 <?php /** * Created by PhpStorm. * User: sa7noun * Date: 5/15/17 * Time: 12:09 PM */ namespace EvalBundle\Controller; use EvalBundle\Entity\Department; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Symfony\Component\HttpFoundation\Request; class DepartmentController extends Controller { /** * Lists all Department entities. * * @Route("/department", name="department_index") * @Method({"GET","POST"} ) * */ public function indexAction(Request $request) { $department = new Department(); $form = $this->createForm('EvalBundle\Form\DepartmentType', $department); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($department); $em->flush(); return $this->redirectToRoute('department_index'); } $em = $this->getDoctrine()->getManager(); $departments = $em->getRepository('EvalBundle:Department')->findAll(); /** * @var $paginator \Knp\Component\Pager\Paginator */ $paginator = $this->get('knp_paginator'); $result = $paginator->paginate( $departments, $request->query->getInt('page', 1), $request->query->getInt('limit', 5) ); return $this->render('EvalBundle:Department:department.html.twig', array( 'departments' => $result, 'form' => $form->createView(), )); } // /** // * Creates a new Department entity. // * // * @Route("/department/new", name="department_new") // * @Method({ "POST"}) // */ // public function newAction(Request $request) // { // $department = new Department(); // $form = $this->createForm('EvalBundle\Form\DepartmentType', $department); // $form->handleRequest($request); // // if ($form->isSubmitted() && $form->isValid()) { // $em = $this->getDoctrine()->getManager(); // $em->persist($department); // $em->flush(); // // return $this->redirectToRoute('department_index'); // } // // return $this->render('EvalBundle:Department:department.html.twig', array( // 'department' => $department, // 'form' => $form->createView(), // )); // } /** * Displays a form to edit an existing department entity. * * @Route("department/{id}/edit", name="department_edit") * @Method({"GET", "POST"}) */ public function editAction(Request $request, Department $department) { $deleteForm = $this->createDeleteForm($department); $editForm = $this->createForm('EvalBundle\Form\DepartmentType', $department); $editForm->handleRequest($request); if ($editForm->isSubmitted() && $editForm->isValid()) { $this->getDoctrine()->getManager()->flush(); return $this->redirectToRoute('department_edit', array('id' => $department->getId())); } return $this->render('EvalBundle:Department:edit.html.twig', array( 'department' => $department, 'edit_form' => $editForm->createView(), 'delete_form' => $deleteForm->createView(), )); } /** * Deletes a department entity. * * @Route("department/{id}", name="department_delete") * @Method({"GET","DELETE"}) */ public function deleteAction(Department $department) { // $response = array( // 'success' => true, // 'message' => '', // 'html' => '', // ); // // $form = $this->createDeleteForm($department); // if ($request->getMethod() == 'DELETE'){ // $form->handleRequest($request); // } // if ($department) { $em = $this->getDoctrine()->getManager(); $em->remove($department); $em->flush(); } return $this->redirectToRoute('department_index'); } /** * Creates a form to delete a department entity. * * @param Department $department The department entity * * @return \Symfony\Component\Form\Form The form */ private function createDeleteForm(Department $department) { return $this->createFormBuilder() ->setAction($this->generateUrl('department_delete', array('id' => $department->getId()))) ->setMethod('DELETE') ->getForm(); } } 

View (pointer):

  {% extends 'default/superAdminBase.html.twig' %} {% block body %} <div class="col-lg-6"> <div class="panel panel-default"> <div class="panel-heading" style="background-color: #0089db"> <h5 style="text-align: center"><b>Départements</b></h5> </div> <!-- /.panel-heading --> <div class="panel-body"> <div class="table-responsive"> <table class="table table-hover table-fixed table-paginated"> <thead> <tr> </tr> </thead> <tbody> {% for department in departments %} <tr> <td> <b>{{ department.name }}</b> <a href="{{ path('department_edit', { 'id': department.id }) }}" class="btn btn-default btn-circle " style="float: right"> <i class="fa fa-edit"></i> </a> <a href="{{ path('department_delete', {'id': department.id}) }}" class="btn btn-danger btn-circle remove-item" data-entity-id="{{ department.id }}" style="float: right" data-toggle="modal"> <span class="glyphicon glyphicon-remove"></span> </a> <div class="modal fade" id="infos"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">x</button> <h4 class="modal-title">Confirmation</h4> </div> <div class="modal-body"> Etes-vous sur de vouloir supprimer ce Département ! </div> <div class="modal-footer"> <button href=" #" class="btn btn-info delete-item" data-dismiss="modal">OUI </button> <button class="btn btn-info" data-dismiss="modal">NON</button> </div> </div> </div> </div> </td> </tr> {% endfor %} </tbody> </table> </div> <!-- /.table-responsive --> </div> <!-- /.panel-body --> </div> <div class="navigation text-center"> {{ knp_pagination_render(departments) }} </div> <!-- /.panel --> <div aria-hidden="true" aria-labelledby="myModalLabel" role="dialog" tabindex="-1" id="myModal-1" class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> {% if app.session.flashBag.has('success') %} <div class="aler alert-success"> {% for msg in app.session.flashBag.get('success') %} {{ msg }} {% endfor %} </div> {% endif %} <button aria-hidden="true" data-dismiss="modal" class="close" type="button">×</button> <h4 class="modal-title"> Ajouter un nouveau département</h4> </div> <div class="modal-body" id="modal-input"> {{ form_start(form,{'attr': {'class': 'form-horizontal','data-parsley-validate':''}}) }} {{ form_widget(form.name,{'attr': {'class': 'form-control','placeholder':'Nom de département', 'data-parsley-required':'true', 'data-parsley-required-message':'le nom ne doit pas être vide :D'}}) }} <br> <div class="form-group"> <div class="col-lg-offset-8 col-lg-4"> <button type="submit" class="btn btn-block btn-primary"><span class="glyphicon glyphicon-plus"></span> Créer </button> </div> </div> {{ form_end(form) }} </div> </div> </div> </div> </div> <a href="#myModal-1" data-toggle="modal" class="btn btn-outline btn-primary "><i class="fa fa-plus"></i>Ajouter un département</a> {% block javascript %} <script src="{{ asset('JS/departmentValidation.js') }}"></script> {% endblock %} {% endblo ck %} 
+5
source share
2 answers

I will answer this mainly so that you get an idea!

so first of all you will have to separate the saved part, because it will no longer return a view, as your indexAction does. Instead, it returns some json data your ajax call might receive

your controller action might look something like this:

  /** * Creates a new Department entity. * * @Route("/department/new", name="department_new") * @Method({ "POST"}) */ public function newAction(Request $request) { $department = new Department(); $form = $this->createForm('EvalBundle\Form\DepartmentType', $department); $form->handleRequest($request); $status = ""; if ($form->isSubmitted() && $form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($department); $em->flush(); $status = "saved"; }else{ $status = "invalid"; } return new JsonResponse(array('status' => $status)); } 

Then you will need to send the correct data to this action

so you need to serialize the form fields into a js object that you can send

here you have a function for what you should include somewhere after loading jquery and before your further code

 $.fn.serializeObject = function() { var o = {}; var a = this.serializeArray(); $.each(a, function() { if (o[this.name] !== undefined) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(this.value || ''); } else { o[this.name] = this.value || ''; } }); return o; }; 

Next, you need to avoid the actual presentation of the non-ajax form, because clicking on the submit button will create a new request, you can prevent this behavior, assuming that the form has a unique eG selector. ID = "newDepartmentForm"

 $(document).on("submit", "#newDepartmentForm", function(e){ e.preventDefault(); return false; }); 

now allows you to assume that you want to save by clicking on the button with a specific identifier

 $(document).on("click", "#mySubmitButton", function(e){ e.preventDefault(); // get the properties and values from the form data = $("#newDepartmentForm").serializeObject(); // always makes sense to signal user that something is happening $('#loadingSpinner').show(); // simple approach avoid submitting multiple times $('#mySubmitButton').hide(); $.ajax({ url: '/department/new', type: 'POST', dataType: 'json', data: data, success:function(data){ $('#loadingSpinner').hide(); $('#mySubmitButton').show(); console.log(data); if(data.status == 'saved'){ console.log("entity saved ! "); } if(data.status == 'invalid'){ console.log("entity submitted was invalid, use try catch and getMessage of eventual errors in you controller action, you can pass all that to the returning array you can receive and parse here ! "); } } }); }); 

it's basically him.

+8
source

Source: https://habr.com/ru/post/1268056/


All Articles