在开发EXTJs的表单程序时,我们经常需要对FormPanel进行数据编辑的工作,而编辑数据的时候,需要把服务端的数据抓取回来并填充取表单的控件中去以完成数据的回填工作,以便于用户的编辑工作,而EXTJs大部分程序会写成以下的方式。
//formPanel的items如下所示: { fieldLabel : '新闻标题', name : 'news.subject', width :400, id : 'subject' },{ fieldLabel:'桌面新闻', name:'isDeskImage', id:'isDeskImage', xtype:'checkbox', handler:function(obj){ if(obj.getValue()){ Ext.getCmp('CheckOutImageButton').show(); }else{ Ext.getCmp('CheckOutImageButton').hide(); } } //................. //加载数据 this.formPanel.getForm().load({ deferredRender : false, url : __ctxPath + '/info/getNews.do?newsId=' + this.newsId, waitMsg : '正在载入数据...', success : function(form, action) { }, failure : function(form, action) { Ext.ux.Toast.msg('编辑', '载入失败'); } });
而该url返回的json数据格式如下所示:
{success:true,data:{"author":"csx","content":"<p>国际关系紧张国际关系紧张国际关系紧张国际关系紧张国际关系紧张国际关</p>","createtime":1284706528000,"firstKeyColumnName":"newsId","id":5,"isDeskImage":1,"issuer":"csx","newsId":5,"newsType":{"class":"com.htsoft.oa.model.info.NewsType_$$_javassist_118","sn":3,"typeId":4,"typeName":"国际新闻"},"replyCounts":3,"status":1,"subject":"国际关系紧张","subjectIcon":"info/news/201009/7de72a2ab73e4ced9779a87606d96b1f.jpg","typeId":4,"updateTime":1285482215000,"viewCounts":51}}
使用以上方式存在以下问题:
1.表单控件必须用id,如"subject",表单控件若用id就可能会跟其他控件存在id冲突。
2.用 formPanel.getForm.load()方法自动加载的时候,经常会出现错误“this.form.el is undefined”
鉴于此,我们对加载进行了扩展,如:
Ext.override(Ext.Panel, { loadData:function(conf){ var ct=this; //遍历该表单下所有的子项控件,并且为它赋值 var setByName=function(container,data){ var items=container.items; if(items!=null){ for(var i=0;i<items.getCount();i++){ var comp=items.get(i); if(comp.items){ setByName(comp,data); continue; } //判断组件的类型,并且根据组件的名称进行json数据的自动匹配 var xtype=comp.getXType(); try{ if(xtype=='textfield' || xtype=='textarea' || xtype=='radio' || xtype=='checkbox' || xtype=='datefield' || xtype=='combo' || xtype=='hidden' || xtype=='datetimefield' ||xtype=='htmleditor' || xtype=='label' || xtype=='fckeditor' ){ var name=comp.getName(); if(name){ if(conf.preName){ name=name.substring(conf.preName.length+1); } var val=eval('data.'+name); if(val){ comp.setValue(val); } } } }catch(e){ //alert(e); } } } }; if (!ct.loadMask) { ct.loadMask = new Ext.LoadMask(Ext.getBody()); ct.loadMask.show(); } Ext.Ajax.request({ method:'POST', url:conf.url, scope:this, success:function(response,options){ var json=Ext.util.JSON.decode(response.responseText); var data=null; if(conf.root){ data=eval('json.'+conf.root); }else{ data=json; } setByName(ct,data); if(ct.loadMask){ ct.loadMask.hide(); ct.loadMask = null; } if(conf.success){ conf.success.call(ct,response,options); } },//end of success failure:function(response,options){ if(ct.loadMask){ ct.loadMask.hide(); ct.loadMask = null; } if(conf.failure){ conf.failure.call(ct,response,options); } } }); } });
使用方式如下:
this.formPanel.loadData({ root : 'data', preName:'news', url : __ctxPath + '/info/getNews.do?newsId=' + this.newsId, success : function(form, action) { }, failure : function(form, action) { Ext.ux.Toast.msg('编辑', '载入失败'); } });
以上方式就不需要表单的控件使用id,并且效率设值对load的方式要快得多,但对于没有id如何取某个控件的值呢,extjs大部分的api都是按id取值。
我们在container上提供了另一个方法,可以按名称取到控件。
Ext.override(Ext.Container, { getCmpByName : function(name) { var getByName = function(container, name) { var items = container.items; if (items != null) { for (var i = 0; i < items.getCount(); i++) { var comp = items.get(i); var cp = getByName(comp, name); if (cp != null) return cp; if (comp.getName && name == comp.getName()) { return comp; break; } } } return null; }; return getByName(this, name); } });