Extjs 自定义控件
// JavaScript Document Ext.namespace('CRM.Panels'); CRM.Panels.UserDetail = Ext.extend(Ext.Panel,{ width:350, height:120, data:{ ID: 0, FirstName: '', LastName: '', Email: '', City: '', Phone:'' }, split:true, tpl: new Ext.XTemplate([ '<div>编号:{ID}</div>', '<div>姓名:{FirstName}-{LastName}</div>', '<div>电话:{Phone}</div>', '<div>城市:{City}</div>', '<div>邮箱:{Email}</div>' ]), initComponent:function(){ CRM.Panels.UserDetail.superclass.initComponent.call(this); if(typeof this.tpl === 'string'){ this.tpl = new Ext.XTemplate(this.tpl); } this.addEvents('UAlert');//注册新事件 this.addListener({//侦听函数 www.2cto.com UAlert: { //注册的新事件 fn:this.onAlert,//调用onAlert方法 scope: this } }); }, ////////////// onAlert: function(){ alert('注册的新事件'); }, UAlert:function(){ this.fireEvent('UAlert'); }, ///////////////////// onRender: function(ct, position){ CRM.Panels.UserDetail.superclass.onRender.call(this, ct, position); if(this.data){ this.update(this.data); } }, update: function(data){ this.data = data; this.tpl.overwrite(this.body, this.data); // this.fireEvent('update',this.data); } }); //把新建的自定义组件注册为一种xtype Ext.reg('UserDetail',CRM.Panels.UserDetail); /*使用: items:[ { region:'west', xtype:'UserDetail', data: userData[0], title:'User Detail' } ]*/ 在页面上: <script language="javascript"> var userData = [ {ID:1,FirstName:'Zhang',LastName:'Jinshan',Email:'zjs@qq.com',Phone:'123456',City:'ZhangPing'}, {ID:2,FirstName:'Wang',LastName:'wu',Email:'wjf@qq.com',Phone:'123456',City:'ZhangPing'} ]; Ext.onReady(function(){ var userDetail = new CRM.Panels.UserDetail({ applyTo:'body', title:'User Detail', data:userData[0] }); updateContact = function(event, el, data){ userDetail.update(data.data);//调用更新数据 } Ext.get('xt').on('click',updateContact,this,{data:userData[1]}); Ext.get('alert').on('click',function(){ userDetail.UAlert(); }); }) </script> <button id="xt">点击</button> <button id="alert">注册的新事件</button> ////////////////////////////////// ExtJS中的面向对象设计,组件化编程思想/** * @author: Lilf * Description: ExtJS中的面向对象设计,组件化变成思想 */ /****************************扩展VTypes类,增加年龄的验证****************************/ Ext.apply(Ext.form.VTypes, { "age": function(_v){ if (/^\d+$/.test(_v)) { var intExp = parseInt(_v); if (intExp < 200) return true; } return false; }, ageText: "请输入正确的年龄格式,如:23" }); /****************************继承自FormPanel的表单组件,用来构件Window***************************/ PersonInfoFormPanel = Ext.extend(Ext.form.FormPanel, { constructor: function(){ PersonInfoFormPanel.superclass.constructor.apply(this, [{ baseCls: "x-plain", buttonAlign: "right", labelWidth: 30, defaultType: "textfield", defaults: { anchor: "95%", labelStyle: "text-align:right" }, items: [{ fieldLabel: "姓名", name: "name" }, { fieldLabel: "年龄", name: "age", vtype: "age"//验证年龄(通过vtype类型来验证) }, { xtype: "combo", mode: "local",//本地数据 readOnly: true, fieldLabel: "性别", displayField: "sex",//显示下拉框的内容 triggerAction: "all",//在选择时,显示所有的项 value: "男",//默认值 store: new Ext.data.SimpleStore({ fields: ["sex"], data: [["男"], ["女"]] }), name: "sex"//绑定字段 }] }]) }, //---以下为PersonInfoFormPanel类对外提供的方法--- getValues: function(){ if (this.getForm().isValid()) return new Ext.data.Record(this.getForm().getValues()); else throw new Error("验证没有通过");//自定义异常 }, setValues: function(_r){ this.getForm().loadRecord(_r); }, reset: function(){ this.getForm().reset(); } }); /**************继承自Window的基类,insertWindow与updateWindow都由此继承****************/ baseWindow = Ext.extend(Ext.Window, { form: null, constructor: function(){ this.form = new PersonInfoFormPanel();//实例化PersonInfoFormPanel类 baseWindow.superclass.constructor.apply(this, [{ plain: true, width: 350, //title: "新增人员", modal: true, resizable: false, closeAction: "hide", defaults: { style: "padding:5px" }, items: this.form, buttons: [{ text: "确 定", handler: this.onSubmitClick,//提交事件调用 scope: this }, { text: "取 消", handler: this.onCancelClick,//取消事件调用 scope: this }] }]); //给insertWindow对象添加事件(事件冒泡) this.addEvents("submit"); }, //提交事件处理函数 onSubmitClick: function(){ try { //发布事件 this.fireEvent("submit", this, this.form.getValues());//调用PersonInfoFormPanel类中自定义的方法getValues this.close(); } catch (_err) { Ext.Msg.alert("系统提示", _err.description);//扑捉自定义错误或异常 } }, //取消事件处理函数 onCancelClick: function(){ this.close(); }, //重置与隐藏事件处理函数 close: function(){ this.form.reset(); this.hide(); } }); /*******************insertWindow类****************************/ insertWindow = Ext.extend(baseWindow, { title: "新增人员" }); /*****************updateWindow类******************************/ updateWindow = Ext.extend(baseWindow, { title: "修改人员", load: function(_r){ this.form.setValues(_r); } }); /********根据上面组件创建新的GridPanel类,它就像我们根据不同的零件设计出来的汽车************ * ExtJs自定义PersonListGridPanel类 * 该类继承自GridPanel[使用Ext.extend(superClass,override Object)方法实现继承], * 并override了该类的构造函?hu数 * 构造函数内部继承自GridPanel的构造函数[apply(this,arguments)实现继承] * 该类实现了如何对外部公布一个事件 * 在构造函数中添加一个事件[this.addEvents("事件名称")] * 然后使用this.fireEvent("事件名称",参数)来发布此事?件 * 最后在客户端调用的时候来订阅该事?jian件 */ PersonListGridPanel = Ext.extend(Ext.grid.GridPanel, { _window: null, _updateWin: null, constructor: function(_url){ this._window = new insertWindow();//insertWindow对象引用 this._updateWin = new updateWindow();//updateWindow对象引用 PersonListGridPanel.superclass.constructor.apply(this, [{ renderTo: Ext.getBody(), width: 550, height: 200, frame: true, layout: "form", //工具栏 tbar: [{ text: "add", handler: function(){ this._window.show(); }, scope: this }, "-", { text: "update", handler: function(){ this._updateWin.show(); try { this._updateWin.load(this.getSelected()); } catch (_err) { Ext.Msg.alert("系统提示", _err.description); this._updateWin.close(); } }, scope: this }, "-", { text: "delete", handler: this.onRemovePerson, scope: this }], enableColumnMove: false, //列模板 columns: [{ header: "Name", menuDisabled: true, dataIndex: "name" }, { header: "Age", menuDisabled: true, dataIndex: "age" }, { header: "Sex", menuDisabled: true, dataIndex: "sex" }], //数据源 store: new Ext.data.JsonStore({ autoLoad: true, url: _url, fields: ["name", "age", "sex"] }), //选中模板 selModel: new Ext.grid.RowSelectionModel({ singleSelect: true, listeners: { "rowselect": { fn: this.onRowSelected, scope: this } } }) }]); //添加事件 this.addEvents("rowselect"); //事件订阅 this._window.on("submit", this.onInsertWinSubmit, this); this._updateWin.on("submit", this.onUpdateWinSubmit, this); }, //----- 以下为自定义方法--------- //获得选中的记录 getSelected: function(){ var _sm = this.getSelectionModel(); if (_sm.getCount() == 0) throw new Error("你没有选中任何记录,请选择一条记录后重试"); return _sm.getSelected(); }, //插入一条记录 insert: function(_r){ this.getStore().add(_r); }, //更新选中的记录 update: function(_r){ try { var _rs = this.getSelected(); var _data = _rs.data; for (var _i in _data) { _rs.set(_i, _r.get(_i)); }; _rs.commit(); } catch (_err) { } }, //删除选中的记录 remove: function(){ try { var _rs = this.getSelected(); Ext.Msg.confirm("系统提示", "你确定删除吗?", function(_btn){ if (_btn == "yes") this.getStore().remove(_rs); }, this); } catch (_err) { Ext.Msg.alert("系统提示", _err.description); } }, //-------以下为自定义事件处理函数------------ //添加事件 onInsertWinSubmit: function(_win, _r){ this.insert(_r); }, //修改事件 onUpdateWinSubmit: function(_win, _r){ this.update(_r); }, //删除事件 onRemovePerson: function(){ this.remove(); }, //选中事件 onRowSelected: function(_sel, _index, _r){ this.fireEvent("rowselect", _r);//发布事件 } }) ////////////// 如何编写ExtJS自定义控件 // 1、引入命名空间 Ext.namespace("ExtUD.Ext");//相当于java中包的作用 // 2、编写自定义控件类 ExtUD.Ext.UDPanel = Ext.extend(Ext.Panel, { title : '自定义控件', html:'自定义控件面板', layout:'fit', getAlert:function(){alert('自定义控件函数!');} }); // 3、注册控件 Ext.reg('udpanel', ExtUD.Ext.UDPanel);//第一个参数为自定义控件的xtype //4、使用自定义控件 Ext.onReady(function() { var temp = new ExtUD.Ext.UDPanel({ renderTo : document.body }); temp.show(); temp.getAlert(); });
如何编写ExtJS自定义控件 // 1、引入命名空间 Ext.namespace("ExtUD.Ext");//相当于java中包的作用 // 2、编写自定义控件类 ExtUD.Ext.UDPanel = Ext.extend(Ext.Panel, { title : '自定义控件', html:'自定义控件面板', layout:'fit', getAlert:function(){alert('自定义控件函数!');} }); // 3、注册控件 Ext.reg('udpanel', ExtUD.Ext.UDPanel);//第一个参数为自定义控件的xtype //4、使用自定义控件 Ext.onReady(function() { var temp = new ExtUD.Ext.UDPanel({ renderTo : document.body }); temp.show(); temp.getAlert(); });
//单文本加单铵钮控件 Ext.Diy.GridCodeName1 = Ext.extend(Ext.Panel, { winWidth:500,//定义弹出窗体的大小 id:'',//窗体ID fieldLabel:'', labelWidth:60, allowBlank:false,//验证是否可为空 blankText:'This field is required',//空白文本 displayField:'NAME',//值1 valueField:'VALUE',//值2 codeField:'CODE',//值3 oldValue:'',//缓存旧值 autoDoLoad:true,//自动加载 pageSize:10,//页显示行数 remoteSort:true,//是否可排序 showLabel: false,//是否显示label initComponent:function() {//在这里定义控件样式与弹出窗体样式等,并获得值 //暂存调用页面传下来的参数 var id=this.id; var tmpNameField=this.displayField; var tmpValueField=this.valueField; var tmpCodeField=this.codeField; var winWidth = this.winWidth; var pageSize = this.pageSize; var remoteSort = this.remoteSort; var tabIndex = -1;//分页 var cm;//列头 if(this.tabIndex!==undefined){ tabIndex = this.tabIndex; } if(this.cm!==undefined){ cm = this.cm; }else{ cm = new Ext.grid.ColumnModel([ new Ext.grid.CheckboxSelectionModel({singleSelect:true}), {id:tmpValueField,header: "值", width: 0, sortable: false, dataIndex: tmpValueField, hidden:true}, {header: "编码", width: 70, sortable: true, dataIndex: tmpCodeField}, {header: "名称", width: 100, sortable: true, dataIndex: tmpNameField} ]); } var readerPanel;//定义要读取的列标题 if(this.readerPanel!==undefined){ readerPanel = this.readerPanel; }else{ readerPanel = new Ext.data.Record.create([ {name: tmpNameField}, {name: tmpValueField}, {name: tmpCodeField} ]); } //读取数据 var reader = new Ext.data.XmlReader({ record: 'ROW', totalRecords: "TOTALCOUNT" }, readerPanel//把数据保存到溶器中 ); //定义存数据的溶器 var tmpStore = new Ext.data.Store({ url: 'servlet/ajaxservlet', reader: reader, remoteSort:remoteSort, listeners:{ load:function(store,records){ Ext.getCmp(id).fireEvent('afterLoad',store,records); } } }); var valueStore = new Ext.data.Store({ url: 'servlet/ajaxservlet', reader: reader, remoteSort:remoteSort, listeners:{ load:function(store,records){ Ext.getCmp(id).setValueByRecord(records[0]); } } }); //判断排序 if(this.sortInfo!==undefined){ tmpStore.setDefaultSort(this.sortInfo.field,this.sortInfo.direction); } this.valueStore = valueStore; this.store = tmpStore; if(this.autoDoLoad){ this.doLoad();//加载数据 } //数据获取情况提示信息 var pagingBar = new Ext.PagingToolbar({ displayInfo:true, emptyMsg:"没有数据显示", displayMsg:"显示从第{0}条数据到第{1}条数据,共{2}条数据", store:tmpStore, pageSize:pageSize }); //数据加载提示 var grid = new Ext.grid.GridPanel({ store: tmpStore, loadMask:{msg:'数据加载中...'}, cm: cm, sm: new Ext.grid.CheckboxSelectionModel({singleSelect:true}), viewConfig: { forceFit:true }, tbar:[{//以下设置查询 xtype:'tbtext', text:'查询关键字:' },{ xtype:'textfield', id:id+'searchItemKey' },' ',{ xtype:'tbbutton', text:'查询', handler:function(){ var tmpSearchKey = Ext.getCmp(id+'searchItemKey').getValue(); Ext.getCmp(id).doSearch(tmpStore,tmpSearchKey,'',''); }, pressed:true }], bbar:pagingBar, buttons: [{ text:'确定', menuAlign:'center', handler : function(){ var record = grid.getSelectionModel().getSelected();// 返回值为 Record 类型 if(record==null){ //Ext.MessageBox.alert('提示', '请选择一条数据!'); Ext.getCmp(id).clearValue(); Ext.getCmp(id).fireEvent('onChange',null,'',''); win.hide(); return; }else{ Ext.getCmp(id).setValueByRecord(record);//以value值为索引填充数据到控件文本框 win.hide(); } } },{ text:'取消', menuAlign:'center', handler : function(){ win.hide(); } } ], autoWidth: true, iconCls:'icon-grid' }); //双击数据行填充数据到控件文本框 grid.on("rowdblclick",function(thisGrid,rowIndex,e){ var record = thisGrid.getStore().getAt(rowIndex); Ext.getCmp(id).setValueByRecord(record); win.hide(); }); //定义窗体详细信息 var win = new Ext.Window({ title: '请选择', width: winWidth, defaults:{autoHeight: true}, modal: true, closeAction: 'hide', bodyStyle: 'padding:10px;', items:grid }); //定义窗体显示内容样式 Ext.apply(this,{ border:false, bodyBorder:false, items:[{ layout:'column', border: false, items:[{ columnWidth:0.9, labelWidth:this.labelWidth, layout: 'form', border: false, items:[{ xtype:'textfield', fieldLabel: this.fieldLabel, anchor:'100%', id:id+'_code', readOnly:true, tabIndex:tabIndex, listeners:{ specialkey : function(field, e){ if (e.getKey() == Ext.EventObject.ENTER) { Ext.getCmp(id).setValueByCode(field.getValue()); } } } }] },{ columnWidth:0.1, border: false, items:[{ xtype:'button', id:id+'_btn', text:' ', handler:function(){ if(Ext.getCmp(id).fireEvent("beforeClick")===false){ return; } win.show(); win.center(); Ext.getCmp(id).fireEvent("afterClick"); }, pressed:true }] }] },{ xtype:'textfield', id:id+'_value', hidden:true }] }); //注册控件事件 Ext.Diy.GridCodeName1.superclass.initComponent.apply(this, arguments); this.addEvents({'onChange':true},{'codeInvalid':true},{'beforeClick':true},{'afterClick':true},{'afterLoad':true}); }, //以下定义控件事件 setLabelDisplay: function(p_showLabel){ this.showLabel=p_showLabel; if(p_showLabel){ document.getElementByIdx_x(this.id).childNodes[0].style.display="none"; var tmpDiv=document.getElementByIdx_x("mylbl_"+this.id); if(tmpDiv){ document.getElementByIdx_x("mylbl_"+this.id+"_td").innerHTML=document.getElementByIdx_x(this.id+"_name").value; tmpDiv.style.display="block"; }else{ tmpDiv = document.createElement_x("div"); tmpDiv.id="mylbl_"+this.id; tmpDiv.innerHTML="<div style='width:100%;height:25px;' class='diyform-label-div'>"+ "<table width='100%' border='0' cellspacing='0' cellpadding='0'><tr ><td width='"+this.labelWidth+"'>"+this.fieldLabel+ ":</td><td id='mylbl_"+this.id+"_td' class='diyform-label-td'>"+ document.getElementByIdx_x(this.id+"_name").value+"</td></tr></table></div>"; tmpDiv.style.width=document.getElementByIdx_x(this.id).style.width; document.getElementByIdx_x(this.id).appendChild(tmpDiv); } }else{ document.getElementByIdx_x(this.id).childNodes[0].style.display="block"; try{document.getElementByIdx_x(this.id).removeChild(document.getElementByIdx_x("mylbl_"+this.id));}catch(ex){} } }, doLoad:function(addCon){ if(addCon!==undefined){ this.clearValue(); this.condition=addCon; } this.doSearch(this.store,'','',''); }, doSearch:function(store,searchKey,value,code){ var tmpParam=[]; tmpParam.push(searchKey); tmpParam.push(value); tmpParam.push(code); if(this.condition!==undefined){ tmpParam.push(this.condition); } var parmObj=createRequestXml(this.classUrl,"GetData",this.method,tmpParam.join(',')); store.baseParams={ requestType: 'requestData4DiyGrid', requestCharSet:'UTF8', requestLisence: '1', requestXml: parmObj }; var pageSize = this.pageSize; store.load({params:{start:0, limit:pageSize}}); }, unedit:function(flag){ Ext.getCmp(this.id+"_btn").setDisabled(flag); Ext.getCmp(this.id+"_code").setDisabled(flag); }, clearValue:function(){ this.oldValue=Ext.getCmp(this.id+'_value').getValue(); Ext.getCmp(this.id+"_value").setValue(''); Ext.getCmp(this.id+"_code").setValue(''); }, changeValue:function(record,value,oldValue){ if(value!=oldValue){ this.fireEvent('onChange',record,value,oldValue); } }, codeInvalid:function(){ this.fireEvent('codeInvalid'); }, setValue:function(value){ if(value==null||value==""){ return; } var record; var i=0,j=this.store.getCount(); for(;i<j;i++){ record = this.store.getAt(i); if(record.get(this.valueField)==value){ this.setValueByRecord(record); break; } } if(i==j){ this.doSearch(this.valueStore,'',value,''); } }, setDtlValue:function(dtl,ifFireEvent){ this.oldValue=Ext.getCmp(this.id+'_value').getValue(); Ext.getCmp(this.id+"_value").setValue(dtl.value); Ext.getCmp(this.id+"_code").setValue(dtl.code); if(ifFireEvent==false){ }else{ this.changeValue(null,dtl.value,this.oldValue); } }, setValueByCode:function(code){ var record; var i=0,j=this.store.getCount(); for(;i<j;i++){ record = this.store.getAt(i); if(record.get(this.codeField)==code){ this.setValueByRecord(record); break; } } if(i==j){ this.doSearch(this.valueStore,'','',code); } }, setValueByRecord:function(record){ if(record!=null){ this.clearValue(); Ext.getCmp(this.id+'_value').setValue(record.get(this.valueField)); Ext.getCmp(this.id+'_code').setValue(record.get(this.codeField)); this.changeValue(record,record.get(this.valueField),this.oldValue); }else{ if(Ext.getCmp(this.id+'_code').getValue()!=""){ Ext.MessageBox.alert('提示','找不到该信息'); Ext.getCmp(this.id+'_code').focus(); } this.clearValue(); this.fireEvent('codeInvalid'); } }, getValue:function(){return Ext.getCmp(this.id+"_value").getValue();} }); // 4、注册控件 Ext.reg('diygridcodename1', Ext.Diy.GridCodeName1);//第一个参数为自定义控件的xtype 调用方式: id:'LM_SPEC', xtype : 'diygridcodename1',//自定义控件 diygridcodename fieldLabel:'规格', labelWidth:80, allowBlank:false, classUrl:classUrl, method:'getSpecInfo', readerPanel:[{name: 'CODE'},{name: 'VALUE'},{name: 'NAME'}], cm:new Ext.grid.ColumnModel([ new Ext.grid.CheckboxSelectionModel(), {header: "编号", width:100, sortable: true,dataIndex: 'NAME'}, {header: "规格", width:120,unedit:false, sortable: true,dataIndex: 'CODE'} ]), listeners:{ onChange:function(p_record,p_value,p_oldValue){ //ifdef = p_record.get("SOM_IFDEFAULT"); }, beforeClick:function(){ if(!checkbaseunit()){ Ext.MessageBox.alert("提示","主要单位不能为空!"); return; } } }, anchor : '98%'//占用总宽度的百份比