使用ajax提交symfony 3表单

时间:2022-11-24 14:55:25

I'm trying to implement my symfony forms / modal ,with ajax to stop reloading page every time time I submit an add/remove and update action, but the problem that I'm not familiar with ajax and I don't know how to do it. Can anyone help me understand the concept.

我正在尝试使用ajax实现symfony表单/模态,每次提交添加/删除和更新操作时都停止重载页面,但是我不熟悉ajax,也不知道如何做这个问题。谁能帮我理解这个概念吗?

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;
    }
}

form :

形式:

<?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 (Index):

视图(索引):

    {% 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 %}

2 个解决方案

#1


11  

i will answer this very basically to let you get an idea !

我基本上会回答这个问题,让你有一个想法!

so first of all you will have to separate the saving part, because it will not return a view anymore like your indexAction does. Instead it returns some json data your ajax call can receive

首先,你需要将保存部分分开,因为它不会像你的indexAction那样返回一个视图。相反,它返回ajax调用可以接收的一些json数据

your controller action may look somelike 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);
            try {
                $em->flush();
                $status = "saved";
            } catch (\Exception $e) {
                    $status = $e->getMessage();
            }    
        }else{
            $status = "invalid";
        }

        return new JsonResponse(array('status' => $status));

   }

Next you will have to send the the correct data to that action

接下来,您必须向该操作发送正确的数据

so you have to serialize the formfields to a js object that you can send

因此,必须将formfields序列化为可以发送的js对象

here you have a function for that that you have to include somewhere after jquery has loaded and before your further code

这里有一个函数,您必须在jquery加载之后或进一步的代码之前的某个地方包含它

$.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 have to avoid actually submitting the form non-ajax, because clicking on the submit button will lead to make a new request, you can prevent that behaviour, assuming the form has some unique selector eG. id="newDepartmentForm"

接下来,您必须避免实际提交表单非ajax,因为单击submit按钮将会产生一个新的请求,您可以防止这种行为,假设表单有一些独特的选择器。id = " newDepartmentForm "

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

now lets assume you want to save by clicking on a button with specific id

现在让我们假设您希望通过单击具有特定id的按钮来保存

$(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').attr("disabled",true);
  $.ajax({
    url: '/department/new',
    type: 'POST',
    dataType: 'json',
    data: data,
    success:function(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 ! ");
      }

      // signal user action is done
      $('#loadingSpinner').hide();
      $('#mySubmitButton').attr("disabled",false);
    }
  });

});

basically thats it.

基本上这就是它。

#2


1  

These are two very useful articles that will help you implement your form in Ajax.

这两篇非常有用的文章将帮助您在Ajax中实现表单。

https://blog.intelligentbee.com/2015/01/19/symfony-2-forms-and-ajax/ http://codemonkeys.be/2013/01/ajaxify-your-symfony2-forms-with-jquery/

https://blog.intelligentbee.com/2015/01/19/symfony-2-forms-and-ajax/ http://codemonkeys.be/2013/01/ajaxify-your-symfony2-forms-with-jquery/

#1


11  

i will answer this very basically to let you get an idea !

我基本上会回答这个问题,让你有一个想法!

so first of all you will have to separate the saving part, because it will not return a view anymore like your indexAction does. Instead it returns some json data your ajax call can receive

首先,你需要将保存部分分开,因为它不会像你的indexAction那样返回一个视图。相反,它返回ajax调用可以接收的一些json数据

your controller action may look somelike 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);
            try {
                $em->flush();
                $status = "saved";
            } catch (\Exception $e) {
                    $status = $e->getMessage();
            }    
        }else{
            $status = "invalid";
        }

        return new JsonResponse(array('status' => $status));

   }

Next you will have to send the the correct data to that action

接下来,您必须向该操作发送正确的数据

so you have to serialize the formfields to a js object that you can send

因此,必须将formfields序列化为可以发送的js对象

here you have a function for that that you have to include somewhere after jquery has loaded and before your further code

这里有一个函数,您必须在jquery加载之后或进一步的代码之前的某个地方包含它

$.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 have to avoid actually submitting the form non-ajax, because clicking on the submit button will lead to make a new request, you can prevent that behaviour, assuming the form has some unique selector eG. id="newDepartmentForm"

接下来,您必须避免实际提交表单非ajax,因为单击submit按钮将会产生一个新的请求,您可以防止这种行为,假设表单有一些独特的选择器。id = " newDepartmentForm "

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

now lets assume you want to save by clicking on a button with specific id

现在让我们假设您希望通过单击具有特定id的按钮来保存

$(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').attr("disabled",true);
  $.ajax({
    url: '/department/new',
    type: 'POST',
    dataType: 'json',
    data: data,
    success:function(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 ! ");
      }

      // signal user action is done
      $('#loadingSpinner').hide();
      $('#mySubmitButton').attr("disabled",false);
    }
  });

});

basically thats it.

基本上这就是它。

#2


1  

These are two very useful articles that will help you implement your form in Ajax.

这两篇非常有用的文章将帮助您在Ajax中实现表单。

https://blog.intelligentbee.com/2015/01/19/symfony-2-forms-and-ajax/ http://codemonkeys.be/2013/01/ajaxify-your-symfony2-forms-with-jquery/

https://blog.intelligentbee.com/2015/01/19/symfony-2-forms-and-ajax/ http://codemonkeys.be/2013/01/ajaxify-your-symfony2-forms-with-jquery/

相关文章