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(增删改查)操作。
数据表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 ); });
本文的模板文件如下:
{% 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 %}
控制器是具体实现逻辑业务的代码,以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 }