用ajax提交symfony 3表格 [英] submit symfony 3 form with ajax

查看:69
本文介绍了用ajax提交symfony 3表格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

mY实体:

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


}

控制器:

<?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();
    }

} 

查看(索引):

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

推荐答案

我基本上会回答这个问题,以便让您有个好主意!

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

首先,您将不得不在服务器端分离保存部分,因为它不再像indexAction那样返回视图.相反,它返回客户端Ajax调用可以接收的一些json数据

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

您的新控制器动作可能看起来像这样:

your new controller action may look somelike this:

   /**
    * Creates a new Department entity.
    *
    * @Route("/department/new", name="department_new")
    * @Method({ "POST"})
    */
   public function newDepartmentAction(Request $request)
   {
        $department = new Department();
        $form = $this->createForm('EvalBundle\Form\DepartmentType', $department);
        $form->handleRequest($request);
        $status = "error";
        $message = "";

        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($department);
            try {
                $em->flush();
                $status = "success";
                $message = "new department saved";
            } catch (\Exception $e) {
                    $message = $e->getMessage();
            }    
        }else{
            $message = "invalid form data";
        }

        $response = array(
            'status' => $status,
            'message' => $message
        );

        return new JsonResponse($response);

        // above is just an example of one way using formtypes, 
        // you can retrieve any parameter you send here like: 
        // $param = $request->get('param');


   }

您可以在所有部门上进行任何想要的分页并返回它们,但是您将需要一种js方式来显示返回的JSON,然后,您不能使用twig,因为视图已经返回,您肯定想要使用具有自动ui刷新功能的任何数据驱动的JS View Model库.

you can do above whatever you want like paginate over all departments and return them, but you would need a js way to display the returned JSON then, you cant use twig for that because the view is already returned, you definetly want to use any datadriven JS View Model lib with automatic ui refresh.

下一步,客户端-您必须从客户端将正确的数据发送到该操作

Next, The client Side - From the client side you will have to send the the correct data to that action

,因此您必须将表单域序列化为一组可以发送到服务器的属性和值.我们将首先将表单序列化为javascript对象.

so you have to serialize the formfields to a set of properties and values that you can send to the server. We will first serialize the form to a javascript object.

这里有一个功能,您必须在加载jquery之后并在进一步的代码之前将其包含在某个地方

here you have a function for that that you have to include somewhere after jquery has loaded 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;
};

接下来,您必须避免实际提交非ajax表单,因为单击提交"按钮将导致提交表单并重新加载页面,假设表单具有一些唯一的选择器eG,我们将避免这种行为.id ="newDepartmentForm"

Next you have to avoid actually submitting the form non-ajax, because clicking on the submit button will lead to submit the form and reload the page, we prevent that behaviour, assuming the form has some unique selector eG. id="newDepartmentForm"

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

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

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

$(document).on("click", "#mySubmitButton", function(e){
  e.preventDefault();
  var form = $("#newDepartmentForm");

  // you could make use of html5 form validation here
  if(!form[0].checkValidity()){

    // To show the native error hints you can fake a click() on the actual submit button
    // which must not be the button #mySubmitButton and shall be hidden with display:none;
    //  example:
    //  <button type="button" id="#mySubmitButton" class"btn btn-default" > Save </button>
    //  <button type="submit" id="#myHIDDENSubmitButton" style="display:none;"></button>
    //
    $("#myHIDDENSubmitButton").click();
    return false;
  }

  // get the serialized properties and values of the form 
  var form_data = form.serializeObject();

  // always makes sense to signal user that something is happening
  $('#loadingSpinner').show();

  // simple approach avoid submitting multiple times
  $('#mySubmitButton').attr("disabled",true);

  // the actual request to your newAction
  $.ajax({
    url: '/department/new',
    type: 'POST',
    dataType: 'json',
    data: form_data,
    success:function(data){

      // handling the response data from the controller
      if(data.status == 'error'){
        console.log("[API] ERROR: "+data.message);
      }
      if(data.status == 'success'){
        console.log("[API] SUCCESS: "+data.message);
      }

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

基本上就是这样.

如果要使站点完全由Ajax驱动,则可以像这样从服务器请求任何数据,例如,您可能希望首先加载所有现有部门,就可以像上面那样进行.但是正如我提到的那样,您将需要一种JS方式来显示数据,诸如单页应用程序之类的术语,MVVM可能值得一看,有很多有用的库,如vue,react,knockout,ember ...等.首选简单的方法,根据模型的复杂性,它们可能不是必需的.对于您的Api,您还可以深入研究高性能的序列化,REST,CRUD,授权,并且不要重复自己的工作.Websocket也可能非常有趣.

if you want to make your site full Ajax-driven, you can request any data from the server like this, for example you may want to load all existing departments first you could just do it like above. But as i mentioned, you would need a JS way to Display your data, terms like single page application, MVVM could be worth a lookup there are a lot of usefull libraries like vue, react, knockout, ember ... etc. if you prefer an easy way, they may not be neccessary depending on the complexity of your model. For your Api you also may dig more into performant serialization, REST, CRUD, authorization and dont repeat yourself. Websockets may also be very interesting.

这篇关于用ajax提交symfony 3表格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆