Symfony2.x + EasyUI datagrid Ajax方式实现数据交互


前言

EasyUI 中的控件大多采用JSON数据格式与后台交互,如果不使用Web应用程序没有使用任何框架,则可以将后台处理的PHP代码写成单独的函数,具体实现参考 PHP - EasyUI DataGrid资料存的方式。如果使用Symfony框架则直接 echo $data 或 echo json_encode()的方式来传递数据就不行了,因为echo是输出到屏幕,而Symfony中动作(Action)的返回结果一般是Response的对象。若果你将要传递的数据$data以这样的形式:

return new Response(json_encode($data));

来传递,会得到一个只显示字符的网页。因为你在Response()中没有指定模板,返回的字符串将直接作为显示的内容。为了更好地使用EasyUI强大的控件库,本文通过Ajax方式实现EasyUI的控件与后台进行交互,实现了一个数据表的CRUD(增删改查)操作。

实现过程

Symfony的应用程序主要包括:数据模型(ORM,每个表都叫一个实体Entity)、控制器(Controller,包括一系列实现具体业务的Action,控制器的作用是解析请求,准备数据供模板中展示)、模板(用于展示,Symfony支持twig、XML和PHP等多种实现形式的模板)、路由(一个YML文件,指定一个请求的URL对应于那个动作Action)和资源文件。详细的介绍参见其他博文。

一、 数据模型

数据表Product  有四个字段,id,name,price和description,实体类的定义如下:

/**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $name;

    /**
     * @ORM\Column(type="decimal", scale=2)
     */
    protected $price;

    /**
     * @ORM\Column(type="text")
     */
    protected $description;

二、模板

模板使用Symfony推荐的twig实现(可以是XML或PHP实现),与EasyUI DataGrid的Demo代码非常类似,唯一不同的是Javascript中对数据的处理。

默认从服务器传入的是json格式的数据,通过调用DataGrid控件的初始化函数$('#dg').datagrid()完成数据的填充。将DataGrid的数据发给后端采用的ajax方式,其形式为

$.ajax({
  type: "POST",
  url: "some.php",
  data: { name: "John", location: "Boston" }
})
  .done(function( msg ) {
    alert( "Data Saved: " + msg );
  });

具体的使用方法可以参考官网: Ajax API。

本文的模板文件如下:

{% extends 'AcmeStoreBundle::layout.html.twig' %}

{% block content %}

	<table id="dg" title="Product List" class="easyui-datagrid" style="width:auto;height:250px"
            toolbar="#toolbar" pagination="true"
            rownumbers="true" fitColumns="true" singleSelect="true">
	    <thead>
	        <tr>
	            <th data-options="field:'id',width:40,align:'center'">ID</th>
	            <th data-options="field:'name',width:100,align:'left'">Name</th>
	            <th data-options="field:'price',width:60,align:'center'">Price</th>
	            <th data-options="field:'description',width:200,align:'left'">Description</th>
	        </tr>
	    </thead>
	</table>
	<script type="text/javascript" >
	
		$('#dg').datagrid({data:[ {{ products|raw  }} ]});		
		
		function deleteProduct(){
		  var row = $('#dg').datagrid('getSelected');
		  if(row){
		    $.messager.confirm('确认','你确认要删除该项目吗?',function(r){
		    	if(r){
		    		$.ajax({
						type: "POST",
						dataType: 'html',
						url: "{{ path('product_delete') }}",
						data: {
							id: row.id,
						},
						error: function(){
							 $.messager.show({ // show error message
							title: 'Error',
							msg: result.errorMsg})},
						success: function(data,textStatus,jqXHR){
							window.location = '{{ path('product_index') }}';
							//alert(data);
							}
					});//ajax
		    	}//if(r)
		    });//$message
		  }else{
		    	$.messager.alert('提示信息:','请先选择您要删除的行?','info');
		  }// if(row)
        }// function deleteProduct()
        
        function editProduct(){
            var row = $('#dg').datagrid('getSelected');
            if (row){
                $('#dlg').dialog('open').dialog('setTitle','Edit Product');
                $('#fm').form('load',row);
            }else{
            	$.messager.alert('提示信息:','请先选择您要编辑的行?','info');
            }
        }
        

        function newProduct(){
		    $('#dlg').dialog('open').dialog('setTitle','New Product');
		    $('#fm').form('clear');
		    
	    }
	    
      function saveProduct(){
      		var raw_str = JSON.stringify($('#fm').serializeArray());
      		//jstr = "["+jstr+"]";
			$('#fm').form('submit',{
				onSubmit: function(){		  
					$.ajax({
						type: "POST",
						dataType: 'json',
						url: "{{ path('product_update') }}",
						data: {
							data_p: raw_str,
						},
						error: function(){
							alert('对不起,保存数据失败!');
							$('#dlg').dialog('close');
						},
						success: function(data,textStatus,jqXHR){
							$('#dlg').dialog('close');
							window.location = '{{ path('product_index') }}';
							//alert(data);
							
							}
					});//ajax
				}
			});
	    }	   
	</script>
	
	<div id="toolbar">
        <a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-add" plain="true" onclick="newProduct()">New Product</a>
        <a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-edit" plain="true" onclick="editProduct()">Edit Product</a>
        <a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-remove" plain="true" onclick="deleteProduct()">Remove Product</a>
    </div>
    
    <div id="dlg" class="easyui-dialog" style="width:400px;height:300px;padding:10px 20px"
            closed="true" buttons="#dlg-buttons">
        <div class="ftitle">Product Information</div>
        <form id="fm" method="post" novalidate>
            <div class="fitem">
                <label>ID:</label>
                <input name="id" readonly="readonly">
            </div>
            <div class="fitem">
                <label>Name:</label>
                <input name="name" class="easyui-validatebox" required="true">
            </div>
            <div class="fitem">
                <label>Price:</label>
                <input name="price" class="easyui-validatebox" required="true">
            </div>
            <div class="fitem" >
                <label>Description:</label>
                <input name="description">
            </div>
        </form>
    </div>
    
    <div id="dlg-buttons">
        <a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-ok" onclick="saveProduct()">Save</a>
        <a href="javascript:void(0)" class="easyui-linkbutton" iconCls="icon-cancel" onclick="javascript:$('#dlg').dialog('close')">Cancel</a>
    </div>
    
    <style type="text/css">
        #fm{
            margin:0;
            padding:10px 30px;
        }
        .ftitle{
            font-size:14px;
            font-weight:bold;
            padding:5px 0;
            margin-bottom:10px;
            border-bottom:1px solid #ccc;
        }
        .fitem{
            margin-bottom:5px;
        }
        .fitem label{
            display:inline-block;
            width:80px;
        }
    </style>
{% endblock %}

三、控制器(Controller类)

控制器是具体实现逻辑业务的代码,以update(更新)和delete(删除)两个操作为例,代码如下:

/**
	 * @Route("/product/update",name="product_update")
	 * @Template("AcmeStoreBundle:Product:show.html.twig")
	 */
	public function updateAction()
	{
		$request = $this->getRequest();
		if ($request->isXmlHttpRequest()) {
			//$request_cont = $request->getContent();
			// get raw json data
			$json_data =  $request->request->get('data_p');
			$data = json_decode($json_data);
			// get properties
			$id = $data[0]->{"value"};
			$name = $data[1]->{"value"};
			$price = $data[2]->{"value"};
			$description = $data[3]->{"value"};
			// update
				
			$em = $this->getDoctrine()->getEntityManager();
			$product = $em->getRepository('AcmeStoreBundle:Product')->find($id);
			if(!$product){
				//throw $this->createNotFoundException(json_encode('No product found with id ='.$id));
				$product = new Product();
				$product->setName($name);
				$product->setPrice($price);
				$product->setDescription($description);
				$em->persist($product);
				$em->flush();
				return  new Response(json_encode('create a product with id = '.$product->getId()));
			}else{
				$product->setName($name);
				$product->setPrice(0.0+$price);
				$product->setDescription($description);
				$em->flush();
				return  new Response(json_encode('update a product with id = '.$description));
			}
	
		}else{
			return  new Response(json_encode('Illegal request for updating product'),400);
		}
	}
	
	/**
	 * @Route("/delete/{id}",name="delete")
	 * @Template("AcmeStoreBundle:Product:index.html.twig"))
	 */
	public  function  deleteAction()
	{
		$request = $this->getRequest();
		if ($request->isXmlHttpRequest()) {
			$id = $request->request->get('id');
			//$id = 2;
			$em = $this->getDoctrine()->getEntityManager();
			$product = $em->getRepository('AcmeStoreBundle:Product')
			->find($id);
			if ($product) {
				$em->remove($product);
				$em->flush();;
			}
			return  new Response(json_encode('delete'.$id));
		}else{
			return  new Response('Cannot delete it .',400);
		}
	}


四、路由

路由是建立控制器的Action与使用模板的对应关系,本文用到的路由项如下:

index:
    path:  /
    defaults: { _controller: AcmeStoreBundle:Default:index }
product_index:
    path:  /product
    defaults: { _controller: AcmeStoreBundle:Product:show}
product_show:
    pattern:  /product/show
    defaults: { _controller: AcmeStoreBundle:Product:show}
product_update:
   pattern:  /product/update
   defaults: { _controller: AcmeStoreBundle:Product:update }
product_delete: 
   pattern: /product/delete
   defaults: { _controller: AcmeStoreBundle:Product:delete }


你可能感兴趣的:(Ajax,easyui,symfony)