jqGrid是蛮强大的表格控件,例子也很多。这里,记录一下自己使用jqGrid4.1.1版本的实作实例。实作效果图:

故障条目列表

选中其中一个条目,点击表格左下脚的铅笔图标,可以编辑此条目:

因为jqGrid升级很快,编码上是否会有所改变,是否还能适应新版本没有去考究。以下实作代码,仅供朋友们参考。

放置表格的html元素:

 
  
  1. <div> 
  2. <table id="jqgajax"></table>  
  3. </div> 
  4. <div id="pjqgajax2"></div> 

引入jqGrid的js文件,以及相关依赖的js文件。然后用js脚本构建表格:

 

 
  
  1. <script type="text/javascript"> 
  2.         jQuery.jgrid.no_legacy_api = true
  3.         jQuery.jgrid.useJSON = true
  4.         </script>  
  5.         <script src="<%=rootPath%>/common/jqGrid/js/jquery.jqGrid.min.js" type="text/javascript"></script> 
  6.         <script src="<%=rootPath%>/common/jqGrid/js/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script> 
  7.          
  8.         <script src="<%=rootPath%>/common/jquery.jec/jquery.jec.js" type="text/javascript"></script> 
  9.      
  10.         <script type="text/javascript">   
  11.             jQuery(document).ready(function(){   
  12.                 jQuery("#jqgajax").jqGrid({  
  13.                     ajaxGridOptions : {type:"POST"},  
  14.                     serializeGridData : function(postdata) {  
  15.                         return postdata;  
  16.                     },  
  17.                     url:'getFaultInjectConfigJson.action?fiBean.appProfile.id=${fiBean.appProfile.id}',  
  18.                     datatype: "json",  
  19.                     colNames:['ID','包名', '递归子包', '类名','方法名','方法描述','方法中调用的方法', 
  20.                         '故障类型', '异常类型', '延迟时间','千条指令注入故障数'],  
  21.                     colModel:[  
  22.                         {name:'fiBean.fic.id', 
  23.                             index:'id',  
  24.                             width:30,  
  25.                             editable:false, 
  26.                             editoptions:{readonly:true,size:10}},  
  27.                         {name:'fiBean.fic.packageName', 
  28.                             index:'packageName',  
  29.                             width:300, 
  30.                             editable:true, 
  31.                             edittype:'text', 
  32.                             editoptions:{size:60,maxlength:100}, 
  33.                             editrules:{required:true}, 
  34.                             formoptions:{elmprefix:'(*)'}},  
  35.                         {name:'fiBean.fic.vPackageRecursive', 
  36.                             index:'packageRecursive',  
  37.                             width:80,  
  38.                             editable:true, 
  39.                             edittype:'select', 
  40.                             editoptions:{value: "Y:Yes;N:No"}}, // 注意,这里不可以写成:editoptions:{value: "Y:Yes; N:No;"}}, 
  41.                         {name:'fiBean.fic.className',index:'className', width:120, align:"left", 
  42.                             editable:true, 
  43.                             edittype:'text', 
  44.                             editoptions:{size:60,maxlength:100}, 
  45.                             editrules:{required:true}, 
  46.                             formoptions:{elmprefix:'(*)'}},  
  47.                         {name:'fiBean.fic.methodName',index:'methodName', width:200, align:"left", 
  48.                             editable:true, 
  49.                             edittype:'text', 
  50.                             editoptions:{size:60,maxlength:100}, 
  51.                             editrules:{required:true}, 
  52.                             formoptions:{elmprefix:'(*)'}},  
  53.                         {name:'fiBean.fic.methodDesc',index:'methodDesc', width:80, 
  54.                             editable:true, 
  55.                             edittype:'text', 
  56.                             editoptions:{size:60,maxlength:100}}, 
  57.                         {name:'fiBean.fic.calledMethod',index:'calledMethod', width:80, 
  58.                             editable:true, 
  59.                             edittype:'text', 
  60.                             editoptions:{size:60,maxlength:100}}, 
  61.                         {name:'fiBean.fic.type',index:'type', width:160, 
  62.                             editable:true, 
  63.                             edittype:'select', 
  64.                             // value部分不要有空格哦,否则,会让你很惊诧的哦! 
  65.                             editoptions:{value: "组件失效:组件失效;让死锁和线程安全易现:让死锁和线程安全易现;组件拖慢:组件拖慢"}}, 
  66.                         {name:'fiBean.fic.exceptType',index:'exceptType', width:180, 
  67.                             editable:true, 
  68.                             edittype:'select', 
  69.                             // value部分不要有空格哦,否则,会让你很惊诧的哦! 
  70.                             editoptions:{value: "java.lang.RuntimeException:java.lang.RuntimeException;" + 
  71.                                 "java.lang.NullPointerException:java.lang.NullPointerException;" + 
  72.                                 "java.lang.reflect.InvocationTargetException;" + 
  73.                                 "java.lang.reflect.UndeclaredThrowableException;" + 
  74.                                 "java.lang.ArithmeticException:java.lang.ArithmeticException;" + 
  75.                                 "java.sql.SQLException:java.sql.SQLException;" + 
  76.                                 "java.lang.NumberFormatException:java.lang.NumberFormatException;" + 
  77.                                 "java.lang.StringIndexOutOfBoundsException:java.lang.StringIndexOutOfBoundsException;" + 
  78.                                 "java.io.IOException:java.io.IOException;" + 
  79.                                 "java.io.EOFException:java.io.EOFException;" + 
  80.                                 "java.io.FileNotFoundException:java.io.FileNotFoundException;" + 
  81.                                 "java.lang.IllegalStateException:java.lang.IllegalStateException;" + 
  82.                                 "java.lang.ClassCastException:java.lang.ClassCastException;" + 
  83.                                 "java.lang.SecurityException:java.lang.SecurityException;"}}, 
  84.                         {name:'fiBean.fic.delayTime',index:'delayTime', width:80, 
  85.                             editable:true, 
  86.                             edittype:'text', 
  87.                             editoptions:{size:60,maxlength:100}}, 
  88.                         {name:'fiBean.fic.density',index:'density', width:180, 
  89.                             editable:true, 
  90.                             edittype:'text', 
  91.                             editoptions:{size:60,maxlength:100}} 
  92.                     ],  
  93.                     rowNum:10,  
  94.                     width:1400,  
  95.                     height:230, 
  96.                     rowList:[10,20,30],  
  97.                     pager: '#pjqgajax2',  
  98.                     sortname: 'name',  
  99.                     viewrecords: true,  
  100.                     sortorder: "desc",  
  101.                     caption:"故障条目",  
  102.                     editurl: "editFaultInjectConfig.action" 
  103.                 }); 
  104.                  
  105.                  
  106.                 jQuery("#jqgajax").jqGrid('navGrid','#pjqgajax2',{edit:true,add:false,del:true,search:false},{width:500, top: 300, left: 300, 
  107.                     "editCaption":"修改故障配置","bSubmit":"提交","bCancel":"取消", "viewPagerButtons":false, "closeAfterEdit":true, "closeOnEscape":true, 
  108.                     "beforeShowForm":function(formid) 
  109.                     { 
  110.                         // get fault inject type value 
  111.                         var typeval = jQuery("#fiBean\\.fic\\.type",formid).val(); 
  112.                         setControlStateByType(typeval); 
  113.                     }, 
  114.                     "onInitializeForm":function(formid) 
  115.                     { 
  116.                         jQuery("#fiBean\\.fic\\.type",formid).change(function(e) { 
  117.                             var typeval = jQuery(this).val(); 
  118.                             setControlStateByType(typeval); 
  119.                         }); 
  120.                     }, 
  121.                     "beforeSubmit" : function (postdata, formid) { 
  122.                         var typeval = jQuery("#fiBean\\.fic\\.type", formid).val(); 
  123.                          
  124.                         // 提交时进行有效性检查 
  125.                         if (typeval == '组件失效') 
  126.                         { 
  127.                             var exceptType = jQuery("#fiBean\\.fic\\.exceptType").val(); 
  128.                             if (exceptType == '') 
  129.                             { 
  130.                                 return [false, "必须选择异常类型!", ""]; 
  131.                             }    
  132.                         } 
  133.                         else 
  134.                         { 
  135.                             var delayTime = jQuery("#fiBean\\.fic\\.delayTime", formid).val(); 
  136.                             if((delayTime == '')||(delayTime.trim() == '')) 
  137.                             { 
  138.                                 return [false, "必须填写延迟时间!", ""] 
  139.                             } 
  140.                         } 
  141.                          
  142.                         return [true, "", ""]; 
  143.                     } 
  144.                 }, 
  145.                 { 
  146.                     top: 0, left: 0 
  147.                 }, 
  148.                 { 
  149.                     top: 400, left: 500 
  150.                 }); 
  151.             }); 
  152.             // 对特殊字符'.',需要转义一下 
  153.             // 注意:根据W3C规定,HTML文档中属性的值是不能包含有这些个特殊字符(“#”和“.”)的 
  154.             // 设置控件的使能 
  155.             function setControlStateByType(typeval) 
  156.             { 
  157.                 if (typeval == '组件失效') 
  158.                 { 
  159.                     jQuery("#fiBean\\.fic\\.exceptType").attr("disabled",false); 
  160.                     jQuery("#fiBean\\.fic\\.delayTime").attr("disabled",true); 
  161.                 } 
  162.                 else if(typeval == '组件拖慢') 
  163.                 { 
  164.                     jQuery("#fiBean\\.fic\\.exceptType").attr("disabled",true); 
  165.                     jQuery("#fiBean\\.fic\\.delayTime").attr("disabled",false); 
  166.                 } 
  167.                 else if(typeval == '让死锁和线程安全易现') 
  168.                 { 
  169.                     jQuery("#fiBean\\.fic\\.exceptType").attr("disabled",true); 
  170.                     jQuery("#fiBean\\.fic\\.delayTime").attr("disabled",false); 
  171.                 } 
  172.                  
  173.                 if (typeval == '组件拖慢') 
  174.                 { 
  175.                     jQuery("#fiBean\\.fic\\.density").attr("disabled", false); 
  176.                 } 
  177.                 else 
  178.                 { 
  179.                     jQuery("#fiBean\\.fic\\.density").attr("disabled", true); 
  180.                 } 
  181.             } 
  182.              
  183.         </script> 

 如果还有一个提交(新增)条目的form,id是saveFiConfigs,那么,新增一条条目后,想要重新载入表格(刷新表格),只要对提交form的行为进行接管,在提交完成后,触发reloadGrid事件即可:

 
  
  1. <script type="text/javascript" class="source below"> 
  2.         jQuery(document).ready(function(){ 
  3.             jQuery('#saveFiConfigs').submit(function() { 
  4.                 // 提交此表单 
  5.                 jQuery(this).ajaxSubmit(function(message) {              
  6.                     // 对于表单提交成功后处理,message为提交页面的返回内容 
  7.                     jQuery("#jqgajax").trigger("reloadGrid"); 
  8.                 }); 
  9.                  
  10.                 // 返回false防止页面跳转 
  11.                 return false; 
  12.             }); 
  13.         });  
  14.     </script> 

jqGrid查询时应当返回符合jqGrid要求的json格式的字符串(可以通过浏览器Chrome浏览器或者火狐,按F12获取到demo的请求和应答数据):

 

 
  
  1. /* 
  2.      * 数据格式示例: 
  3.      String result = "{\"page\":\"1\",\"total\":2,\"records\":\"13\"," + 
  4.         "\"rows\":[{\"id\":\"12\",\"cell\":[\"12\",\"2007-10-06\",\"Client 2\",\"700.00\",\"140.00\",\"840.00\",null]}," + 
  5.         "{\"id\":\"10\",\"cell\":[\"10\",\"2007-10-06\",\"Client 2\",\"100.00\",\"20.00\",\"120.00\",null]}," + 
  6.         "{\"id\":\"11\",\"cell\":[\"11\",\"2007-10-06\",\"Client 1\",\"600.00\",\"120.00\",\"720.00\",null]}," + 
  7.         "{\"id\":\"9\",\"cell\":[\"9\",\"2007-10-06\",\"Client 1\",\"200.00\",\"40.00\",\"240.00\",null]}," + 
  8.         "{\"id\":\"13\",\"cell\":[\"13\",\"2007-10-06\",\"Client 3\",\"1000.00\",\"0.00\",\"1000.00\",null]}," + 
  9.         "{\"id\":\"8\",\"cell\":[\"8\",\"2007-10-06\",\"Client 3\",\"200.00\",\"0.00\",\"200.00\",null]}," + 
  10.         "{\"id\":\"7\",\"cell\":[\"7\",\"2007-10-05\",\"Client 2\",\"120.00\",\"12.00\",\"134.00\",null]}," + 
  11.         "{\"id\":\"6\",\"cell\":[\"6\",\"2007-10-05\",\"Client 1\",\"50.00\",\"10.00\",\"60.00\",\"\"]}," + 
  12.         "{\"id\":\"5\",\"cell\":[\"5\",\"2007-10-05\",\"Client 3\",\"100.00\",\"0.00\",\"100.00\",\"no tax at all\"]}," + 
  13.         "{\"id\":\"4\",\"cell\":[\"4\",\"2007-10-04\",\"Client 3\",\"150.00\",\"0.00\",\"150.00\",\"no tax\"]}]," +  
  14.         "\"userdata\":{\"amount\":3220,\"tax\":342,\"total\":3564,\"name\":\"Totals:\"}}"; 
  15.      */ 
  16.     public String noTranGetFiConfigDataJson(int appProfileId, int page, int rows) { 
  17.         // 查询故障注入配置信息 
  18.         String hql = "from FaultInjectConfig where parent_id = ?"
  19.         List<FaultInjectConfig> faultInjectConfigs = faultInjectDAO.findByHql(hql, Arrays.asList(appProfileId)); 
  20.          
  21.         int records = faultInjectConfigs.size(); 
  22.         int total = records/rows + 1
  23.          
  24.         StringBuilder sb = new StringBuilder(); 
  25.         sb.append("{\"page\":").append("\"").append(page).append("\","
  26.             .append("\"total\":").append("\"").append(total).append("\","
  27.             .append("\"records\":").append("\"").append(records).append("\","
  28.             .append("\"rows\":["); 
  29.          
  30.         for(int i=(page-1)*rows; (i<records)&&(i<page*rows); i++) { 
  31.             FaultInjectConfig fiConfig = faultInjectConfigs.get(i); 
  32.             sb.append(fiConfig.toJson()); 
  33.              
  34.             int j = i + 1
  35.             if ((j<records)&&(j<page*rows)) { 
  36.                 sb.append(","); 
  37.             } 
  38.         } 
  39.          
  40.         sb.append("]}"); 
  41.          
  42.         return sb.toString(); 
  43.     } 

Action只要写回构造好的json串,jqGrid就会将数据填塞进表格,上面代码的服务端代码展示:

 
  
  1. public String getFaultInjectConfigJson() { 
  2.  
  3.         int appProfileId = fiBean.getAppProfile().getId(); 
  4.         String result = faultInjectService.noTranGetFiConfigDataJson(appProfileId, 
  5.                 page, rows); 
  6.         writeToClient(result); 
  7.         return null
  8.     } 

这里顺带讲一下,jqGrid在请求时,会根据请求不同,携带不同的请求参数。譬如:

 

 
  
  1. // 这两个参数是jqGrid执行删除操作时需要的参数 
  2.     private int id; 
  3.     private String oper; 
  4.  
  5.     // 这些是jqGrid执行查询操作时需要的参数 
  6.      
  7.     // 显示第几页 
  8.     private int page; 
  9.     // 每页显示几条记录 
  10.     private int rows; 
  11.      
  12.     // 这些参数暂时没有用到 
  13.     //private boolean _search;  //为true时,表明此次的动作是搜索行为 
  14.     //private String nd; 
  15.     // 排序字段 
  16.     //private String sidx; 
  17.     // 排序方式(asc/desc) 
  18.     //private String sord; 
  19.      
  20.     //private String searchField;   //for example: packageName 
  21.     //private String searchOper;    //for example: cn 
  22.     //private String searchString;  //for example: hi1 

上面注释掉的代码,是jqGrid提供高级功能时需要使用到的参数(譬如,搜索、排序等)。

提交编辑时,oper的值是:"edit",删除时,oper的值是:"del",看edit功能的后台代码(可见,修改和删除,在jqGrid的眼里都是edit):

 
  
  1. public String editFaultInjectConfig() { 
  2.     // 编辑 
  3.     if ("edit".equals(oper)) { 
  4.         System.out.println("heeh"); 
  5.         // 由于jqGrid在传递id时,不会采用id所设定的名字(也许是我们没有深入钻研jqGrid),所以,需要我们将id手动的传递到对象 
  6.         fiBean.getFic().setId(id); 
  7.         // 将外部表示转换为内部表示 
  8.         fiBean.getFic().changeDescToInnerValue(); 
  9.          
  10.         // save可能会报这个异常:Caused by: org.hibernate.NonUniqueObjectException 
  11.         faultInjectService.mergeFaultInjectConfig(fiBean.getFic()); 
  12.     } else if ("del".equals(oper)) {    // 删除 
  13.         System.out.println("enter delFaultInjectConfig(): id: " + id); 
  14.         faultInjectService.deleteFaultInjectConfig(id); 
  15.     } 
  16.  
  17.     return null

以上实例是基于jqGrid4.1.1结合Struts2的使用。好了,到这里,实例讲解结束。