Extjs 自定义控件

// JavaScript Document
Ext.namespace('CRM.Panels');
CRM.Panels.UserDetail = Ext.extend(Ext.Panel,{
     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,
              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(),
             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: "值",  0, sortable: false, dataIndex: tmpValueField, hidden:true},
    {header: "编码",  70, sortable: true, dataIndex: tmpCodeField},
    {header: "名称",  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: '请选择',
          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='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: "编号", 100, sortable: true,dataIndex: 'NAME'},
          {header: "规格", 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%'//占用总宽度的百份比

  

原文地址:https://www.cnblogs.com/anbylau2130/p/3637635.html