似乎,不能做增删改查(IDUS),就好像失去了 意义一样,前不久,带我的人给了我一个图片,要求我用Extjs做,以前只是听老师说过Extjs,知道2.0以后要付费,就没什么用,本人Jquery用的也不是很多.脚本方面,还是很薄弱的.这次居然要我....认了吧,没什么不能克服的.还好在公司有人带,不过也别太指望别人带,人家也有他的事情要做.
我是用的是Extjs 3.3.0(上面给我的) API最好准备好,配置相关的,可以去查下API,同样是脚本,Extjs 跟Jquery的侧重点可完全不同啊...刚开始很难适应..尤其是对脚本本来就不熟的我
最难的不是 页面的开发,而是兼容性的测试,不知道为什么 这个好像不兼容问题很明显 我开发的时候用的是遨游,经测试 在火狐下面也可以,但是IE下面好像不行,我无语了
这代码,就当是熟悉下ExtJs吧.网上的其他我参考了很多很多,但是没找到在 页面操作的 我指的是 增加 删除 修改 在内容里面,而不是在上面的tbar或者是下面的 bbar
我开发的时候,上面的人只给我了一张图片,功能布局差不多就这样,网上找了,很多版本都是 直接编辑 删除 与新增放在 bbar或者是tbar里面的
很明显,我做得是 单行编辑 与删除,某一行处于编辑状态时,其他行不允许编辑,不允许删除,处于编辑行状态的不允许删除,点击编辑以后是 保存
收入支出改变了 金额改变了 以后 余额也会改变,余额不允许直接修改,修改完 收入支出 金额以后,系统自动结算余额 时间不可修改.
看图片:
更新以后,弹出操作成功或者失败
下面是代码,由于后台底层用的是公司多层架构,故后台代码不全.但功能我会尽量解释清楚的,初学者,还是多看看API吧
先介绍一下 文件 extjs里面是网上下载的,本次开发 只用了其中的 两个脚本文件,一个 样式文件 对应的路径为
l
ink href="extjs/resources/css/ext-all.css" rel="stylesheet" type="text/css" /> <script src="extjs/adapter/ext/ext-base.js" type="text/javascript"></script> <script src="extjs/ext-all.js" type="text/javascript"></script>
为了简化操作,所以也使用了 一点 Jquery
default 页面是主要的页面,另外一个 DiarySource是数据传递文件
这其中还有使用到 json数据传递,其中有把数据 格式化成json的,比如吧List<T>格式化成json着一些列的操作,我曾在网上收了一些代码,有些在处理时间格式的,会有点问题 转换不过来 json的时间格式比较特殊 里面含有英文字母
经测试 Newtonsoft.Json.dll 这个类库很强大,也很方便,大家可以到网上去下载
以下是代码,我就不在代码里面详细介绍了,看起来也不方便,我留在最后做总结的时候,再细细的说明
Default.aspx 页面
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>无标题页</title> <link href="extjs/resources/css/ext-all.css" rel="stylesheet" type="text/css" /> <script src="extjs/adapter/ext/ext-base.js" type="text/javascript"></script> <script src="extjs/ext-all.js" type="text/javascript"></script> <script type="text/javascript" src="Jquery/jquery-1.4.1.js" ></script> <style type="text/css"> /* Override standard grid styles (add colour to vertical grid lines) */ .vline-on .x-grid3-col { border-left: 1px solid #EEEEEE; border-right: 1px solid #D2D2D2; } /* Also remove padding from table data (to compensate for added grid lines) */ .vline-on .x-grid3-row td, .x-grid3-summary-row td { padding-left: 0px !important; padding-right: 0px !important; } </style> <script type="text/javascript"> Ext.onReady(function () { Ext.QuickTips.init(); function formatDate(value) { return value ? value.dateFormat('Y/m/d') : ''; }; // shorthand alias var fm = Ext.form; // custom column plugin example var checkColumn = new Ext.grid.CheckColumn({ header: "Indoor?", dataIndex: 'indoor', width: 55 }); /////----下面生成一段 模拟的 GUID function newGuid() { var guid = ""; for (var i = 1; i <= 32; i++){ var n = Math.floor(Math.random()*16.0).toString(16); guid += n; if((i==8)||(i==12)||(i==16)||(i==20)) guid += "-"; } return guid; } //创建的当前的操作栏的 function pctChange(val){ var a=""; if($("#txt_hiden").val()==val){ a='<a href="#" id="'+val+'" οnclick="EditAndSave(this.id)">保存</a> '; }else{ a='<a href="#" id="'+val+'" οnclick="EditAndSave(this.id)">编辑</a> '; } var c='<a href="#" id="'+val+'" οnclick="deleteMe(this.id)">删除</a>'; return a+c; } ////创建 grid 的 列 // _ID _CreateTime _IncomeOrExpense _Money _Category _Introduce _Balance var cm = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(),//为了方便看,故显示了行号 { //hidden:true,//隐藏字段 id: 'ID', header: "编号", dataIndex: '_ID', width: 60 }, { header: "日期", dataIndex: '_CreateTime', width: 130, renderer: formatDate // ,editor: new fm.DateField({ // format: 'Y/m/d', // minValue: '06/01/01', // disabledDays: [0, 6], // disabledDaysText: '时间' // }) }, { header: "收入/支出", dataIndex: '_IncomeOrExpense', typeAhead: true, width: 80, editor: new Ext.form.ComboBox({ typeAhead: true, triggerAction: 'all', transform: 'IncomeOrExpense', lazyRender: true, listClass: 'x-combo-list-small' }) }, { header: "金额", dataIndex: '_Money', renderer:'usMoney', width: 100, editor: new fm.NumberField({ allowBlank: false, allowNegative: false, aline:'right', maxValue: 100000 }) }, { header: "类型", dataIndex: '_Category', width: 110, editor: new Ext.form.ComboBox({ typeAhead: true, triggerAction: 'all', transform: 'Category', lazyRender: true, listClass: 'x-combo-list-small' }) },{ header: "说明", dataIndex: '_Introduce', width: 110, editor: new fm.TextField({ allowBlank: false }) }, { header: "余额", dataIndex: '_Balance', width: 100, renderer: 'usMoney' //余额是算出来的,不是直接写进去的 },{ header: "操作", dataIndex: '_ID', width: 120, renderer:pctChange } ]); cm.defaultSortable = true;//所有列默认排序 ////ID CreateTime IncomeOrExpense Money Category Introduce Balance var Diary = Ext.data.Record.create([ {name:'_ID',type:'int'}, {name:'_CreateTime',type:'date',type: 'date', dateFormat: 'Y/m/d'}, {name:'_IncomeOrExpense',type:'string'}, {name:'_Money',type:'float'}, {name:'_Category',type:'string'}, {name:'_Introduce',type:'string'}, {name:'_Balance',type:'float'} ]); // 创建数据源 var vproxy = new Ext.data.HttpProxy({ url: 'DiarySource.aspx', reader: new Ext.data.JsonReader({ record: 'DiaryEnter' },Diary), sortInfo: { field: '_ID', direction: 'ASC' } }); var store = new Ext.data.Store({ proxy: vproxy }); // 创建可编辑的表单 var grid = new Ext.grid.EditorGridPanel({ id:'grid', store: store, cm: cm, cls : 'vline-on', renderTo: 'editor-grid', width: 840, height: 300, autoExpandColumn: 'ID', title: '日记账录入', frame: true, plugins: checkColumn, clicksToEdit: 1, //设置单行选中 删除的时候,就删除这一行 selModel: new Ext.grid.RowSelectionModel({ singleSelect: true }), tbar: [ { xtype:'hidden', id:'action', value:'QUERY_T_SYS_USER_ACTION' },'账户:' ,{ xtype : "combo", name : 'startTime', id : 'cbo_account', width : 140, maxLength : 25 } ,'商店:' ,{ xtype : "combo", name : 'startTime', id : 'cbo_shop', width : 140, maxLength : 25 },'月份' ,{ xtype : "textfield", name : '月份', id : 'txt_month', width : 120, maxLength : 10 } ,{ xtype : "button", name : 'startTime', id : 'btn_select', text:'查询', width : 60, },'期初余额', { html : ' <span id="span_startMoney">10000.00</span> </br>' }, '期末余额', { html : ' <span id="span_endMoney">11111.00</span> ' } ] ,header:true, bbar: [ { text: '增加交易', handler: function () { var n = grid.getStore().getCount();// 获得总行数 var p = new Diary({ _ID:newGuid() , _CreateTime:(new Date()).clearTime(), _IncomeOrExpense:"收入", _Money:0,_Category:"其它", _Introduce:"新增数据", _Balance:0 }); grid.stopEditing();// 停止编辑 store.insert(n, p);// 插入到store里面的最后一行 } }//增加一行的结束 ] }); // 触发数据加载 store.load(); // ----编辑以后 触发afteredit事件 // grid.on("afteredit", afterEdit, grid); grid.on("beforeedit", beforeedit, grid); }); Ext.grid.CheckColumn = function (config) { Ext.apply(this, config); if (!this.id) { this.id = Ext.id(); } this.renderer = this.renderer.createDelegate(this); }; Ext.grid.CheckColumn.prototype = { init: function (grid) { this.grid = grid; this.grid.on('render', function () { var view = this.grid.getView(); view.mainBody.on('mousedown', this.onMouseDown, this); }, this); }, onMouseDown: function (e, t) { if (t.className && t.className.indexOf('x-grid3-cc-' + this.id) != -1) { e.stopEvent(); var index = this.grid.getView().findRowIndex(t); var record = this.grid.store.getAt(index); record.set(this.dataIndex, !record.data[this.dataIndex]); } }, renderer: function (v, p, record) { p.css += ' x-grid3-check-col-td'; return '<div class="x-grid3-check-col' + (v ? '-on' : '') + ' x-grid3-cc-' + this.id + '"> </div>'; } }; //----------------------------------------------------------------------------------- /////--------点击保存的时候触发的事件 function beforeedit(e){ var record = e.record; if($("#txt_hiden").val()!=record.get("_ID")){ //alert("不可编辑"); return false; } } function EditAndSave(id) { var a=document.getElementById(id); var grid=Ext.getCmp("grid"); var store=grid.getStore();//得到当前对象的Store var record = grid.getSelectionModel().getSelected(); if($(a).html()=="编辑"){ //先取值,看能不能编辑,编辑保存以后,才能编辑下一条数据 if($("#txt_hiden").val()==""||$("#txt_hiden").val()==record.get("_ID")){ $("#txt_hiden").val(record.get("_ID")); }else{ alert("请先保存已经修改的行"); return; } $(a).html("保存");//处理完了以后,文本变为保存 }else{ //------------------------------------点击保存----//XX保存的时候,只管当前的这一条数据,不管其他的修改的数据---------------------// //有了这一条数据的ID,保存修改的值,肯定是当前ID所在行的数据 store.modified所有修改过的值 var modified=store.modified; $("#obj_hiddenModified").val(modified); if($("#txt_hiddenModified").val()==modified){ Ext.Msg.alert("警告", "没有任何需要更新的数据!"); $("#txt_hiden").val(""); $(a).html("编辑");//处理完了以后,文本变为编辑 return false; } //alert($("#obj_hiddenModified").val()); updateData(modified); //-------------------------------------------------// //点击保存以后,把 临时值 清空 $("#txt_hiden").val(""); //点击曾加一条,直接插入数据 $(a).html("编辑");//处理完了以后,文本变为编辑 } } // --------点击删除时触发的事件 function deleteMe(id) { //删除前,先判断 是不是 当前 对象处于编辑状态 如果是,那么不能直接删除 if($("#txt_hiden").val()!="") { alert("有行数据,处于编辑状态的行,不能直接删除,请先保存再删除"); return false; } ////-----真删除,到那时好像没有刷新数据--已解决 Ext.MessageBox.confirm("请确认", "真的要删除该数据?", function (button, text) { if (button == "yes") { //临时生成的一条记录,还没有 插入数据库,可直接删除 if(id.length>10){ var grid=Ext.getCmp("grid"); var store=grid.getStore();//得到当前对象的Store var record = grid.getSelectionModel().getSelected() store.remove(record); Ext.Msg.alert("信息", "数据删除成功!", function () { }); return; } //执行删除操作 Ext.Ajax.request({ url: "Default.aspx", params: { id: id }, method: "POST", success: function (response) { var grid=Ext.getCmp("grid"); var store=grid.getStore();//得到当前对象的Store var record = grid.getSelectionModel().getSelected(); store.remove(record); grid.store.reload(); Ext.Msg.alert("信息", "数据删除成功!", function () { }); }, failure: function (response) { Ext.Msg.alert("警告", "数据更新失败,请稍后再试!"); } }); } else { //Ext.MessageBox.alert("操作结果", "取消删除!"); } }); // }//删除事件的结尾 //----------保存修改------------------- function updateData(modified) { var json = []; Ext.each(modified, function (item) { json.push(item.data); }); if (json.length > 0) { Ext.Ajax.request({ url: "Default.aspx", params: { data: Ext.util.JSON.encode(json) }, method: "POST", success: function (response) { Ext.Msg.alert("信息", "数据更新成功!", function () { var grid=Ext.getCmp("grid"); var store=grid.getStore();//得到当前对象的Store store.reload(); $("#txt_hiddenModified").val($("#obj_hiddenModified").val()); }); }, failure: function (response) { Ext.Msg.alert("警告", "数据更新失败,请稍后再试!"); } }); } else { Ext.Msg.alert("警告", "没有任何需要更新的数据!"); } } </script> </head> <body> <form id="form1" runat="server"> <div style="display:none;"> 初期余额:<span id="startMoney" runat="server">0</span>期末余额:<span id="endMoney" runat="server">0</span></div> <div> <select name="IncomeOrExpense" id="IncomeOrExpense" style="display: none;"> <option value="收入">收入</option> <option value="支出">支出</option> </select> <select name="Category" id="Category" style="display: none;"> <option value="社会公积金">社会公积金</option> <option value="缴纳公司税金">缴纳公司税金</option> <option value="工资">工资</option> <option value="其它">其它</option> </select> <div id="editor-grid" style=" margin-left:200px;"></div> <div id="hello"></div> </div> <div style=" display:none;"><input type="text" id="txt_hiden" /> </div> <input type="hidden" id="txt_hiddenModified" /><input type="hidden" id="obj_hiddenModified" /> </form> </body> </html>
-----------------------Default.aspx 页面代码 完毕 ------------------ --------------------------------Default.aspx .cs 代码------ public partial class _Default : System.Web.UI.Page { DiaryEnterManager diaryManager = new DiaryEnterManager();//业务逻辑层的 类,处理数据的 protected void Page_Load(object sender, EventArgs e) { ChangeEndMoney(); Bond(); } /// <summary> /// 执行删除任务 ajax发请求 id /// </summary> public void Bond() { bool result = false; //删除数据 if (Request.Form["id"]!=null) { int id = Convert.ToInt32(Request.Form["id"]); result= diaryManager.DeleteDiaryEnterById(id); if (result) { ChangeEndMoney(); } } //更新数据 if (Request.Form["data"]!=null) { string a = Request.Form["data"].ToString(); List<DiaryEnter> list = new DiaryEnterJson().Json2DiaryEnterList(a); DiaryEnter dia; if (list.Count>1) { dia = list[list.Count - 1];//得到最后一个 } else { dia = list[0]; } //期末余额 decimal money = Convert.ToDecimal(this.endMoney.InnerText); if (dia._ID==0) { // ID为0,表示插入数据 传递这个对象 然后到逻辑层处理 result=diaryManager.InsertDiaryEnter(dia._CreateTime, dia._IncomeOrExpense, dia._Money, dia._Category, dia._Introduce, money); if (result) { ChangeEndMoney(); } } else { //修改数据数据,修改一条,很多地方都要重新修改啊 //它上面的,的紧挨着的一条数据的钱的余额 就是 它的 末期余额 要用来计算的 //得到一个 decimal类型的数据 //下面是用来修改 没有改变金额 钱的情况下的 .仅用来做测试方法 result = diaryManager.UpdateDiaryEnterById(dia._ID, dia._IncomeOrExpense, dia._Money, dia._Category, dia._Introduce); if (result) { ChangeEndMoney(); } } } } public void Bind() { ChangeEndMoney(); } /// <summary> /// 更新期末余额 /// </summary> public void ChangeEndMoney() { //得到数据库里面 的期末余额 if (diaryManager.EndMoney()>0) { this.endMoney.InnerText = diaryManager.EndMoney().ToString(); } else { this.endMoney.InnerText = "10000"; } } } ----------------------------下面是 DiarySource.aspx页面的代码 看仔细了 就只有一行,别吓到了------------------- <%@ Page Language="C#" AutoEventWireup="true" CodeFile="DiarySource.aspx.cs" Inherits="DiarySource" %> --------------------就只有这一行 页面一定要 干净-,页面上的数据,在后台输出,这个页面就是 上面 Extjs的Grid的数据源 常见的数据源有2种:一种是xml文件,另一种就是 json格式的的数据源,这个页面输出的,就是json格式的 文本--后台代码如下:------------- public partial class DiarySource : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Bind(); } /// <summary> /// 将 List集合转换为json文本 /// </summary> public void Bind() { List<DiaryEnter> list = new DiaryEnterManager().getAllDiaryEnter();//从逻辑层查到所有的数据 string jsonStr = new DiaryEnterJson().List2json(list);//这个方法 是公共类的方法,将List<T> 格式化为 json Response.Write(jsonStr);//json格式的文本输出到页面,当做数据源 } } -------------DiaryEnterJson 类 --------- using Newtonsoft.Json;//注意引用命名空间 public class DiaryEnterJson { public DiaryEnterJson() { } /// <summary> /// 把一个 List 序列化为一个 json数组 的字符串/> /// </summary> /// <param name="list"></param> /// <returns></returns> public string List2json(List<DiaryEnter>list) { if (list==null) { return ""; } return JavaScriptConvert.SerializeObject(list); ; } /// <summary> /// 将 json字符串转换为一个集合 /// </summary> /// <param name="strJson">参数 json字符串</param> /// <returns>返回一个日记集合</returns> public List<DiaryEnter> Json2DiaryEnterList(string strJson) { //得到的是一个对象 List<DiaryEnter> list = new List<DiaryEnter>(); foreach (JavaScriptObject item in (JavaScriptArray)JavaScriptConvert.DeserializeObject(strJson)) { DiaryEnter diary = new DiaryEnter(); diary._ID = Convert.ToInt32(item["_ID"].ToString().Length>10?"0":item["_ID"]); diary._IncomeOrExpense = item["_IncomeOrExpense"].ToString(); diary._Money = Convert.ToDecimal(item["_Money"]); diary._CreateTime = Convert.ToDateTime(item["_CreateTime"]); diary._Category = item["_Category"].ToString(); diary._Balance = Convert.ToDecimal(item["_Balance"]); diary._Introduce = item["_Introduce"].ToString(); list.Add(diary); } return list; } }
-------------代码完毕-----主要就是这些了-----------------------------
--------------------------******************最后说明:***************----------------------------
Extjs 的效果很好,与jquery的侧重点不相同,jquery有强大的选择器,可以迅速方便的得到 所要的对象,但是,如何把这些拼接到一起,还是需要做很多的事情,比如要显示一个 表格 要自己动手写很多代码,而用 Extjs 就很方便,只需要配置相应的属性就行
Extjs 的提示框 就跟WinForm的提示框效果差不多,可以自定义,说句心里话 普通js的 alert();与confirm();确实有点ugly...
在extjs文件夹下的 examples里面有很多例子可以看,看下,你就知道Extjs的强大了,另外就是 extjs可以把jquery代码当做基类来用!!!
页面最上面 的 tbar 的功能没有实现,昨晚增删改查以后,我就没做了.
功能大家看看 就好了,细节就是 调用 ajax的方法要仔细看,之前我还不知道怎么从页面用js代码 去调用后台,做完这个以后,感觉受益良多,做了2个星期....相信你会比我优秀的.
---------------------------------这其中不是一帆风顺的 遇到的问题要一个一个的解决-------------------------------------------
首先是:数据的显示 显示需要数据源,数据源的确定,弄了2天,不知道那个页面要是干净的才行,连 html 的标签都不能有 这个困扰了我2天
原本是在网上找 json处理的类,找了一些,使用了,后来发现 时间格式处理不好,查资料找了一天
数据显示成功,后面的 编辑 删除功能没有做,页面上也没有,查了一天的资料,后来查到资料可以自定义 类容,才把 编辑 删除 加上去
增加一行,很简单,就不介绍了,另外说的是 删除功能
删除 发送ajax请求,到后台删除数据很简单,关键是 页面的数据 如何才能删掉,之前想了个办法 是删除数据源里面的一条,然后重新加载,当失败了,后来找到资料,可以直接在页面上删除 ,试了一下午,终于在页面上删除了
家下来最麻烦的就是 数据的 编辑与保存了
编辑的时候,逻辑处理很多 编辑完了 保存的时候,后台还要计算 相应的数据,都要一连串的改动,这不仅是页面上的值要改,sql数据库里面的数据也要改,这就有一连串的逻辑处理,批量修改数据与数据的计算,我比较笨,那一晚做到凌晨2点半才把逻辑写完>..
编辑的时候,要控制好,不能让其他的行被删除了,不然数据 变动不过来,单行操作是比较保险的,网上很多代码,都是直接在页面上修改 然后调用 修改后的事件来做的,
该事件有个不足之处,事件触发条件只能写在 grid内部,外部是不能 声明 处理后的这个事件,也就是说,把编辑放在页面内部去做,afterEdit事件根本用不着
本人 本着学习的精神,如果大家有更好的方法来实现,愿共同探讨.
代码下载:Extjs