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自定義控件
// 一、引入命名空間
Ext.namespace("ExtUD.Ext");//至關於java中包的做用
// 二、編寫自定義控件類
ExtUD.Ext.UDPanel = Ext.extend(Ext.Panel, {
   title : '自定義控件',
   html:'自定義控件面板',
   layout:'fit',
   getAlert:function(){alert('自定義控件函數!');}
  });
// 三、註冊控件
Ext.reg('udpanel', ExtUD.Ext.UDPanel);//第一個參數爲自定義控件的xtype

//四、使用自定義控件
Ext.onReady(function() {
var temp = new ExtUD.Ext.UDPanel({
   renderTo : document.body
  });
 temp.show(); 
 temp.getAlert();
});
 
如何編寫ExtJS自定義控件
// 一、引入命名空間
Ext.namespace("ExtUD.Ext");//至關於java中包的做用
// 二、編寫自定義控件類
ExtUD.Ext.UDPanel = Ext.extend(Ext.Panel, {
   title : '自定義控件',
   html:'自定義控件面板',
   layout:'fit',
   getAlert:function(){alert('自定義控件函數!');}
  });
// 三、註冊控件
Ext.reg('udpanel', ExtUD.Ext.UDPanel);//第一個參數爲自定義控件的xtype

//四、使用自定義控件
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();}
 });
// 四、註冊控件
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%'//佔用總寬度的百份比
相關文章
相關標籤/搜索