dojo DataGrid实现表格数据编辑的解决方案
在官网上看见的DataGrid编辑非常简单,但我实现的时候总是出现问题。经过N久的摸索,终于搞定了,期间出现了多处困难,下面说些解决办法的流程。
我实现的表格在页面加载时是不显示数据,只有通过表单像服务器提交查询数据后才刷新表格。
首先新建DataGrid:
gridLayout =[{ defaultCell: { editable: true, type: cells._Widget, styles: \'text-align: center;\' }, cells: [ { name: "WBS", field: "wbs", width: "60px"}, /* { name: "ID", field: "configId", width: "240px",editable:false}, */ { name:"系统/设备/部件",field:"equipName",width:"120px"}, { name: "配置项名称", field: "configName", width: "100px" }, { name: "位置名称", field: "locationName", width: "80px" }, { name: "设备所属部门", field: "deptName", width: "120px" }, { name: "状态", field: "status", width: "40px" }, { name: "删除", field: "inc_number", width:"60px",formatter: getDeleteButton }, { name: "保存", field: "saveButton", width:"60px",formatter: getSaveButton }, { name: "详细", field:"updateLink", width:"60px",formatter:getUpdateLink} ] }]; grid = new DataGrid({ structure: gridLayout, "class": "grid", escapeHTMLInData: false, noDataMessage: "没有配置数据" }, "gridDiv" ); grid.startup();
然后为提交按钮添加事件处理程序,向服务器端发送请求
//查询按钮的点击事件处理程序 var queryButton=dom.byId("queryButton"); on(queryButton, "click", function(evt){ equipName = dom.byId("equipName").value; wbsId = dom.byId("wbsId").value; populateDataGrid(equipName,wbsId); }); //通过设备名和wbs向服务器段查询数据后填充grid表格 function populateDataGrid(equipName,wbsId) { if((equipName=="")&&(wbsId=="")) return; request.get("configurationMaintainingQueryAction.action?configurationMaintaining.equipName="+equipName+"&configurationMaintaining.wbsId="+wbsId,{handleAs : "json"}) .then(function(data) { store = new Memory({data : data , idProperty: "configId" }); dataStore = new ObjectStore({objectStore : store}); grid.store = dataStore; grid._refresh(); }); }
显示数据没问题的,但是就是不能编辑。网上查到的资料也少。感觉用DOJO的远没有JQUERY的多,至少查中文资料是这样的。
后来发现是在DataGrid新建时,必须有store属性才能EDIT。但是我在页面初始加载时,并不希望表格显示数据,所以给DataGrid设置一个空的ObjectStore就可以,修改新建表格代码:
store=new Memory(); dataStore=new ObjectStore({objectStore : store}); grid = new DataGrid({ structure: gridLayout, store:dataStore, "class": "grid", escapeHTMLInData: false, noDataMessage: "没有配置数据" }, "gridDiv" ); grid.startup();
这步完成了,表格就可以编辑了。但是发现和官网上的例子不同的时,此时表格的数据编辑之后在客户端就无法保存,会出现空白的显示情况。
解决办法是实现编辑完成的事件处理程序:
var configIds=new Array(); grid.on("ApplyEdit",function(rowIndex) { grid.update(); var rowdata = grid.getItem(rowIndex); var configId = rowdata["configId"]; for(i=0;i<configIds.length;i++) { if(configIds[i].rowIndex==rowIndex) return; } configIds.push({rowIndex:rowIndex,configId:configId}); });
添加grid.update()既可以解决问题,同时可以在这里获取表格编辑数据准备下一步向服务器端发送。
到这里在客户端网页已经能够实现表格数据的编辑了,和官网的例子一样。
下一步实现真正的服务器端数据修改,这里的思路是收集所有编辑过的单元行数据,然后一起POST到服务器端。代码如下:
function getSaveButton(col, rowIndex) { var new_button = new dijit.form.Button( { label : \'保存\', showLabel : false, iconClass : "dijitEditorIcon dijitEditorIconSave", \'class\' : \'gridButton\', onClick : saveClick }); function saveClick(evt) {//删除按钮的删除事件处理程序 if (confirm("确定保存修改?")) { evt.stopPropagation(); evt.preventDefault(); var configurationMaintainings=[]; for(i=0;i<configIds.length;i++) { var rowdata = grid.getItem(configIds[i].rowIndex); var temp=new Object(); temp.configId=rowdata["configId"]; temp.wbs=rowdata["wbs"]; temp.equipName=rowdata["equipName"]; temp.configName=rowdata["configName"]; temp.locationName=rowdata["locationName"]; temp.deptName=rowdata["deptName"]; configurationMaintainings.push(temp); } request.post("configurationMaintainingAction.action?mode=update",{data : jsonString});//先服务器提交删除参数 populateDataGrid(equipName,wbsId);//刷新DataGrid configIds=new Array();//清空 } } new_button._destroyOnRemove = true; return new_button; }
但是这是发现在服务器端无法接受到request的数据。后来在CHROME调试中发现在Network面板中观察到提交的数据是[[object Object],[object Object],[object Object]]这样的形式。也没有太在意(实际上是不懂)。
网上说数据也弄成JSON就可以了,我一直以为自己提交的就是JSON,总以为是服务器端的事情。后来看了别人的例子才知道在JS中必须要做这样的转换,还好DOJO提供了JSON类,加一句代码就可以。将request.post语句修改如下:
var jsonString = JSON.stringify(configurationMaintainings); request.post("configurationMaintainingAction.action?mode=update",{data : jsonString});//先服务器提交删除参数
顺便说一句,CHROME真心好用。
然后在服务器端接受就可以,这里用了谷歌的GSON包。非常简单,部分代码如下:
cms.clear(); ActionContext ac=ActionContext.getContext(); Map<String, Object> map=ac.getParameters(); String jsonStr=""; for(Map.Entry<String, Object> entry:map.entrySet()){ System.out.println(entry.getKey()+"--->"+entry.getValue()); jsonStr=entry.getKey(); break; } //创建一个Gson对象 Gson gson = new Gson(); //创建一个JsonParser JsonParser parser = new JsonParser(); //通过JsonParser对象可以把json格式的字符串解析成一个JsonElement对象 JsonElement el = parser.parse(jsonStr); //把JsonElement对象转换成JsonObject JsonObject jsonObj = null; if(el.isJsonObject()){ jsonObj = el.getAsJsonObject(); } //把JsonElement对象转换成JsonArray JsonArray jsonArray = null; if(el.isJsonArray()){ jsonArray = el.getAsJsonArray(); } ConfigurationMaintaining cm=new ConfigurationMaintaining(); Iterator it = jsonArray.iterator(); while(it.hasNext()){ JsonElement e = (JsonElement)it.next(); //JsonElement转换为JavaBean对象 cm=gson.fromJson(e, ConfigurationMaintaining.class); cms.add(cm); } configurationMaintaining.update(cms);
到这里工作基本完了,但是运行后又发现一个问题
即表格编辑后,去点击保存按钮,最后一个编辑的cell,系统不是默认为ApplyEdit状态,所以该单元格数据不会被修改。
本来想在saveButton的事件处理程序中,添加grid的update方法,但是也不起作用。
后来发现,当saveButton的事件处理程序调用完了,依然会除非该单元格的ApplyCellEdit。所以只要在这个事件中加点代码就可以,为了避免每一次ApplyCellEdit事件都触发代码,设置一个isSaveButtonClicked布尔量,在saveButton中打开,在ApplyCellEdit中判断并关闭。代码如下:
grid.on("ApplyCellEdit",function(cell,rowIndex) { if(isSaveButtonClicked==true) { var rowdata=grid.getItem(rowIndex); var configurationMaintainings=[]; var temp=new Object(); temp.configId=rowdata["configId"]; temp.wbs=rowdata["wbs"]; temp.equipName=rowdata["equipName"]; temp.configName=rowdata["configName"]; temp.locationName=rowdata["locationName"]; temp.deptName=rowdata["deptName"]; configurationMaintainings.push(temp); var jsonString = JSON.stringify(configurationMaintainings); request.post("configurationMaintainingAction.action?mode=update",{data : jsonString});//先服务器提交删除参数 configIds=new Array();//清空 isSaveButtonClicked=false; grid.update(); populateDataGrid(equipName,wbsId);//刷新DataGrid alert("配置修改项成功!"); } });
到这里问题完全解决。
JSP页面完整代码:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP \'configurationMaintaining.jsp\' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <link rel="stylesheet" href="/lss/css/lssCss.css" /> <link rel="stylesheet" href="/lss/dojoroot/dijit/themes/claro/claro.css" /> <link rel="stylesheet" href="/lss/dojoroot/dojox/grid/resources/Grid.css" /> <link rel="stylesheet" href="/lss/dojoroot/dojox/grid/resources/claroGrid.css" /> <script src="/lss/dojoroot/dojo/dojo.js" ></script> <script> var equipName,wbsId; var grid, dataStore, store; require(["dojox/grid/DataGrid", "dojox/grid/cells", "dojox/grid/cells/dijit", "dojo/dom", "dojo/on", "dojo/request", "dojo/store/Memory", "dojo/data/ObjectStore", "dojo/json", "dijit/form/Button", "dojo/domReady!"], function(DataGrid,cells,cellsDijit,dom,on,request,Memory,ObjectStore,JSON){ gridLayout =[{ defaultCell: { editable: true, type: cells._Widget, styles: \'text-align: center;\' }, cells: [ { name: "WBS", field: "wbs", width: "60px"}, { name:"系统/设备/部件",field:"equipName",width:"120px"}, { name: "配置项名称", field: "configName", width: "100px" }, { name: "位置名称", field: "locationName", width: "80px" }, { name: "设备所属部门", field: "deptName", width: "120px" }, { name: "状态", field: "status", width: "40px" }, { name: "删除",editable:false,field: "deleteButton", width:"60px",formatter: getDeleteButton }, { name: "保存", editable:false,field: "saveButton", width:"60px",formatter: getSaveButton }, { name: "详细",editable:false, field:"updateLink", width:"60px",formatter:getUpdateLink} ] }]; store=new Memory(); dataStore=new ObjectStore({objectStore : store}); grid = new DataGrid({ structure: gridLayout, store:dataStore, "class": "grid", escapeHTMLInData: false, noDataMessage: "没有配置数据" }, "gridDiv" ); grid.startup(); //查询按钮的点击事件处理程序 var queryButton=dom.byId("queryButton"); on(queryButton, "click", function(evt){ equipName = dom.byId("equipName").value; wbsId = dom.byId("wbsId").value; populateDataGrid(equipName,wbsId); }); //通过设备名和wbs向服务器段查询数据后填充grid表格 function populateDataGrid(equipName,wbsId) { if((equipName=="")&&(wbsId=="")) return; request.get("configurationMaintainingQueryAction.action?configurationMaintaining.equipName="+equipName+"&configurationMaintaining.wbsId="+wbsId,{handleAs : "json"}) .then(function(data) { store = new Memory({data : data , idProperty: "configId" }); dataStore = new ObjectStore({objectStore : store}); grid.store = dataStore; grid._refresh(); }); } //获得DataGrid表格的更新按钮 function getUpdateLink(col, rowIndex){ var rowdata=grid.getItem(rowIndex); var configId=rowdata["configId"]; return ("<a href=configurationInputAction.action?mode=detail&configurationInput.configId="+configId+">详细 </a>"); } //获得DataGrid表格的删除按钮 function getDeleteButton(col, rowIndex) { var new_button = new dijit.form.Button( { label : \'删除\', showLabel : false, iconClass : "dijitEditorIcon dijitEditorIconRemoveFormat", \'class\' : \'gridButton\', onClick : deleteClick }); function deleteClick(evt) {//删除按钮的删除事件处理程序 if (confirm("确定删除该配置项吗?")) { var rowdata = grid.getItem(rowIndex); var configId = rowdata["configId"]; /* evt.stopPropagation(); evt.preventDefault(); */ request.get("configurationMaintainingAction.action?mode=delete&configurationMaintaining.configId="+configId);//先服务器提交删除参数 populateDataGrid(equipName,wbsId);//刷新DataGrid alert("删除配置项成功!"); } } new_button._destroyOnRemove = true; return new_button; } var configIds=new Array();//存放编辑过的数据行id var isSaveButtonClicked=false;//保存按钮是否点击过 //编辑完成事件处理 grid.on("ApplyEdit",function(rowIndex) { grid.update(); var rowdata = grid.getItem(rowIndex); var configId = rowdata["configId"]; for(i=0;i<configIds.length;i++) { if(configIds[i].rowIndex==rowIndex) return; } configIds.push({rowIndex:rowIndex,configId:configId}); }); //单元格编辑完成事件处理,在保存按钮后的事件处理程序跑完后会触发该事件 grid.on("ApplyCellEdit",function(cell,rowIndex) { if(isSaveButtonClicked==true) { var rowdata=grid.getItem(rowIndex); var configurationMaintainings=[]; var temp=new Object(); temp.configId=rowdata["configId"]; temp.wbs=rowdata["wbs"]; temp.equipName=rowdata["equipName"]; temp.configName=rowdata["configName"]; temp.locationName=rowdata["locationName"]; temp.deptName=rowdata["deptName"]; configurationMaintainings.push(temp); var jsonString = JSON.stringify(configurationMaintainings); request.post("configurationMaintainingAction.action?mode=update",{data : jsonString});//先服务器提交删除参数 configIds=new Array();//清空 isSaveButtonClicked=false; grid.update(); populateDataGrid(equipName,wbsId);//刷新DataGrid alert("配置修改项成功!"); } }); //获得DataGrid表格的保存按钮 function getSaveButton(col, rowIndex) { var new_button = new dijit.form.Button( { label : \'保存\', showLabel : false, iconClass : "dijitEditorIcon dijitEditorIconSave", \'class\' : \'gridButton\', onClick : saveClick }); function saveClick(evt) {//删除按钮的删除事件处理程序 if (confirm("确定保存修改?")) { isSaveButtonClicked=true; evt.stopPropagation(); evt.preventDefault(); var configurationMaintainings=[]; for(i=0;i<configIds.length;i++) { var rowdata = grid.getItem(configIds[i].rowIndex); var temp=new Object(); temp.configId=rowdata["configId"]; temp.wbs=rowdata["wbs"]; temp.equipName=rowdata["equipName"]; temp.configName=rowdata["configName"]; temp.locationName=rowdata["locationName"]; temp.deptName=rowdata["deptName"]; configurationMaintainings.push(temp); } var jsonString = JSON.stringify(configurationMaintainings); request.post("configurationMaintainingAction.action?mode=update",{data : jsonString});//先服务器提交删除参数 populateDataGrid(equipName,wbsId);//刷新DataGrid configIds=new Array();//清空 } } new_button._destroyOnRemove = true; return new_button; } }); </script> </head> <body bgcolor="#bae87c" class="claro"> <br /> <table width="800px" align="center"> <tr><td> <!-- <form id="formNode"> --> <fieldset > <legend><font color="red"><b>查询</b></font></legend> <table width="100%"> <tr><td align="right">系统/设备/部件 </td><td align="left"><input type="text" name="configurationMaintaining.equipName" id="equipName"/></td> <td align="right">WBS</td><td align="left"><table class="selectTable"><s:select list="configurationMaintaining.wbses" listValue="wbs" listKey="wbsId" name="configurationMaintaining.wbsId" id="wbsId"/></table></td> </tr> <tr><td colspan="3"></td><td align="center"><input type="button" id="queryButton" value="查询"></td></tr> </table> </fieldset> <!-- </form> --> <br /> <form> <fieldset > <legend><font color="red"><b>配置信息</b></font></legend> <div id="gridDiv" style="width:100%;height: 200px;" > </div> </fieldset> </form> </td></tr> </table> </body> </html>