`

Extjs ComboBox的擴展

 
阅读更多

 作用:          

         在程序中,经常会遇到这种情况:即获取其它地方的参数,在本ComboBox中带上参数查询出结果,把结果中的某些字段值设置到所需要的地方(其它地方):

[同时在Grid中也支持],相关参数若不设置即就是普通的ComboBox!

 

 

Ext.ns("dnet.base");
dnet.base.AbstractCombo = Ext.extend(Ext.form.ComboBox, {

	 _dataProviderFields_  :null   //要顯示的字段即record($Model)
	,_dataProviderName_ : null     //組件名字
	,fieldMapping : null        //設置到哪個Field中
	,paramMapping: null    // ex: paramMapping: [{lovField:"...lovFieldName", dsField: "...dsFieldName"} ]
    ,callFromGrid:null     //若此Combo則Grid中則需要設置(required if this combox in grid)
    ,storeUrl:null
    ,minChars:0
    ,listEmptyText:"Can't find fit data !"
	/** 創建Store**/
	,_createStore_: function() {

		this.store = new Ext.data.Store({
	        remoteSort:true
	       ,reader: new Ext.data.JsonReader(
	   		 	{totalProperty: 'totalCount',idProperty: 'id',root: 'data',messageProperty: 'message'}
				,Ext.data.Record.create(this._dataProviderFields_)
			)
	       ,listeners: { "exception":{ fn:  this.proxyException, scope:this }}
	       ,url:this.storeUrl
		})
	    this.store.proxy.getConnection().async = false;//同步
	}
    /** 更改了源碼中的doQuery方法,重寫 !**/
	/*源碼中何處調用doQuery()方法
	 initQuery : function(){
        this.doQuery(this.getRawValue());
     },
	*/
    ,doQuery : function(q, forceAll){
        q = Ext.isEmpty(q) ? '' : q;
        var qe = {
            query: q,
            forceAll: forceAll,
            combo: this,
            cancel:false
        };

        if(this.fireEvent('beforequery', qe)===false || qe.cancel){
            return false;
        }
        q = qe.query;
        forceAll = qe.forceAll;
        if(forceAll === true || (q.length >= this.minChars)){
            if( (this.lastQuery !== q) || (this.paramMapping != null && this.paramMapping.length>0) ){
                this.lastQuery = q;
                if(this.mode == 'local'){
                    this.selectedIndex = -1;
                    if(forceAll){
                        this.store.clearFilter();
                    }else{
                        this.store.filter(this.displayField, q);
                    }
                    this.onLoad();
                }else{
                    //this.store.baseParams[this.queryParam] = q;//這是源碼中的code
                    var bp = {}
                    bp[this.queryParam]=q;
					if (this.paramMapping != null) {
					   this._mapFilterFields_(bp);
					}
					/**若想將所有參數作為一個對象傳遞過去的話,
					 * 可下一句改為this.store.baseParams["data"]=Ext.encode(bp)
					 * 其中data是你傳遞過去的對象名.
					 */
                    this.iteratorSetbaseParam(bp);                   
                    this.store.load({
                        params: this.getParams(q)
                    });
                    this.expand();
                }
            }else{
                this.selectedIndex = -1;
                this.onLoad();
            }
        }
    }
    ,iteratorSetbaseParam:function(bp){
    	this.store.baseParams[this.queryParam]=bp[this.queryParam];
    	if(this.paramMapping !=null){
    	   for(var i=0;i<this.paramMapping.length;i++){
    	      this.store.baseParams[this.paramMapping[i].param]=bp[this.paramMapping[i].param];
    	   }
    	}
    }
    /** 如果設置了分頁pagesize大小,則store加載時會有分頁參數! **/
    ,getParams : function(q){
//        var p = {};
//        //p[this.queryParam] = q;
//        if(this.pageSize){
//            p.start = 0;
//            p.limit = this.pageSize;
//        }
//        return p;
        var params = {},
            paramNames = this.store.paramNames;
        if(this.pageSize){
            params[paramNames.start] = 0;
            params[paramNames.limit] = this.pageSize;
        }
        return params;
    }
    /** 更改了源碼中的assertValue()方法!**/
	,assertValue  : function(){
        var val = this.getRawValue(),
            rec = this.findRecord(this.displayField, val);
        if(!rec && this.forceSelection){
			this.setRawValue("");
			if(val.length > 0 && val != this.emptyText){
				//this.el.dom.value = Ext.value(this.lastSelectionText, '');
                this.applyEmptyText();
            }else{
                this.clearValue();
            }

            this._mapReturnFields_(null);

        }else{
            if(rec){
                // onSelect may have already set the value and by doing so
                // set the display field properly.  Let's not wipe out the
                // valueField here by just sending the displayField.
                this._mapReturnFields_(rec);
                if (val == rec.get(this.displayField) && this.value == rec.get(this.valueField)){

				    return;
                }
                val = rec.get(this.valueField || this.displayField);
            } else {
            	if (val != this.value ) {
            		this._mapReturnFields_(null);
            	}			   
			}
			if (this.getValue() != val) {
               this.setValue(val);
			}

        }
    }
    /** onSelect 暫時更改與源碼中一樣! **/
    ,onSelect : function(record, index){
        if(this.fireEvent('beforeselect', this, record, index) !== false){
            this.setValue(record.data[this.valueField || this.displayField]);
            if(this.fieldMapping!=null){
            	this._mapReturnFields_(record);//在select事件中設置一次,失去焦點的時候可以再設置一次(add after)
            }
            this.collapse();

            this.fireEvent('select', this, record, index);
        }
    }
    /** Return  **/
    ,_mapReturnFields_: function(crec) {   // crec combo selected record[Selected Record]
    	if(!Ext.isEmpty(this.callFromGrid)){
    		//注意這裡會根據你設置的SelectionModel不同而不同,具體情況根據你設置來定
    		 var mrec=this.callFromGrid.getSelectionModel().getSelected();//獲得選中的第一條記錄(即編輯的紀錄)
       		 this._mapReturnFieldsExecute_(crec,mrec);//crec是combo選中的紀錄,mrec是combo所在Grid行的紀錄,即把combo中的紀錄設置到Grid中
    	}else{
    		 this._mapReturnFieldsExecute_(crec);
    	}
    }

    ,_mapReturnFieldsExecute_: function(crec, mrec) {   // crec combo selected record
    	if(crec!=null){//若選中紀錄時才設置值到其他字段中
	        if (this.fieldMapping != null) {
	           for(var i=0, len=this.fieldMapping.length; i<len; i++ ) {
		          if (!Ext.isEmpty(this.callFromGrid)) {
		            mrec.set( this.fieldMapping[i].field ,crec.get(this.fieldMapping[i].column) )  ;
		          }else {
		            Ext.getCmp(this.fieldMapping[i].field).setValue( crec.get(this.fieldMapping[i].column) );
		            Ext.getCmp(this.fieldMapping[i].field).fireEvent( "change");
		          }
			   }
			}
    	}else{//否則不只設置值,並且將之前的值清空.
    	    if (this.fieldMapping != null) {
	           for(var i=0, len=this.fieldMapping.length; i<len; i++ ) {
		          if (!Ext.isEmpty(this.callFromGrid)) {
		            mrec.set( this.fieldMapping[i].field ,"")  ;
		          }else {
		            Ext.getCmp(this.fieldMapping[i].field).setValue("") ;
		            Ext.getCmp(this.fieldMapping[i].field).fireEvent( "change");
		          }
			   }
			}
    	}
	}
	/** Filter **/
    ,_mapFilterFields_: function(bp) {   // empty object which is added to store.baseParams
    	if(!Ext.isEmpty(this.callFromGrid)){//如果是在GridPanel或EditorGridPanel中
    		 //注意這裡會根據你設置的SelectionModel不同而不同,具體情況根據你設置來定
    		 var mrec=this.callFromGrid.getSelectionModel().getSelected();//獲得選中的第一條記錄(即編輯的紀錄)
       		 this._mapFilterFieldsExecute_(bp,mrec);
    	}else{
    		 this._mapFilterFieldsExecute_(bp);
    	}
    }
    ,_mapFilterFieldsExecute_: function(bp, mrec) {   // bp:basePrams for combo query;mrec:Grid Edit Record
		var newParamVal;
    	var oldParamVal;
        if (this.paramMapping != null) {
        	for(var i=0, len=this.paramMapping.length; i<len; i++ ) {
	        	if(!Ext.isEmpty(this.callFromGrid)){//如果是在GridPanel或是EditorGridPanel中
				   	newParamVal = (!Ext.isEmpty(this.paramMapping[i].field))?mrec.get( this.paramMapping[i].field ):this.paramMapping[i].value ;
				   	//從設置的參數字段中讀取值
	        	}else{
	        	    newParamVal = (!Ext.isEmpty(this.paramMapping[i].field))?Ext.getCmp(this.paramMapping[i].field).getValue():this.paramMapping[i].value;
	        	    //從設置的
	        	}
	        	oldParamVal = this.store.baseParams[this.paramMapping[i].param];//原來查詢參數baseParam中對應字段值
	        	/*以下不用判斷,若判斷的話則第一次之後就會不帶參數,不符合我們的需要。
		        if (newParamVal != oldParamVal) {//如果參數有變動則查詢否則不查
		            bp[this.paramMapping[i].param]=newParamVal;
		        }
		        */
	        	bp[this.paramMapping[i].param]=newParamVal;
	       }
        }
    }
    /** 其實就是調整若配置了大小寫配置,則轉化為大小寫! **/
    ,getValue : function(){
		var v = null;
        if(this.valueField){
            v= Ext.isDefined(this.value) ? this.value : '';
        }else{
            v= Ext.form.ComboBox.superclass.getValue.call(this);
        }
        if (this.initialConfig["caseRestriction"] == "uppercase" && !Ext.isEmpty(v) )v=v.toUpperCase();
        return v;
    }
    /** proxy exception**/
    , proxyException: function(dataProxy, type, action , options , response , arg ) {
        if(type=="response") {
          this.afterAjaxFailure(response , options);
        } else {
           alert(response.message.substr(0,1500));
        }
	  }
    , afterAjaxFailure: function(response , options) {
      	this.dc____ajaxfailure(response , options);

	  }

    /** initEvent **/
	,initEvents : function(){
        Ext.form.ComboBox.superclass.initEvents.call(this);



        this.keyNav = new Ext.KeyNav(this.el, {
            "up" : function(e){
                this.inKeyMode = true;
                this.selectPrev();
            },

            "down" : function(e){
                if(!this.isExpanded()){
                    this.onTriggerClick();
                }else{
                    this.inKeyMode = true;
                    this.selectNext();
                }
            },

            "enter" : function(e){
                this.onViewClick(true);
                //if(this.isExpanded()){
                	e.stopEvent();
                	e.stopPropagation();
                	e.preventDefault();
				//}
				return false;
            },

            "esc" : function(e){
                this.collapse();
            },

            "tab" : function(e){
                if (this.forceSelection === true) {
                    this.collapse();
                } else {
                    this.onViewClick(false);
                }
                return true;
            },

            scope : this,

            doRelay : function(e, h, hname){
                if(hname == 'down' || this.scope.isExpanded()){
                    // this MUST be called before ComboBox#fireKey()
                    var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
                    if(!Ext.isIE && Ext.EventManager.useKeydown){
                        // call Combo#fireKey() for browsers which use keydown event (except IE)
                        this.scope.fireKey(e);
                    }
                    return relay;
                }
                return true;
            },
            forceKeyDown : true,
            defaultEventAction: 'stopEvent'
        });
        this.queryDelay = Math.max(this.queryDelay || 10,
                this.mode == 'local' ? 10 : 250);
        this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
        if(this.typeAhead){
            this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
        }
        if(!this.enableKeyEvents){
            this.mon(this.el, 'keyup', this.onKeyUp, this);
        }
    }
	,onRender : function(ct, position){
		dnet.base.AbstractCombo.superclass.onRender.call(this, ct, position);
	}
	
	,dc____ajaxfailure:function(response , options) {
		Ext.MessageBox.hide();

      	var msg = response.responseText;
		if (msg && msg.length > 2000) { msg = msg.substr(0,2000);}
      	Ext.Msg.show({
	        //  title: 'HTTP:'+response.status+' '+ response.statusText
	          msg: msg
	         ,buttons: {ok:'OK'} //, cancel:'Details'
	         ,scope:this
	         ,icon: Ext.MessageBox.ERROR
	         ,_detailedMessage_:response.responseText

	      });
	}
});
Ext.reg('xcombo', dnet.base.AbstractCombo);

    

 

 

 

   以下是使用的例子:

   此种情况是在Grid中的使用情况,即获取brandName列的值赋给参数brandCode,并把参数作为productCategory这个comboBox的Store的参数来查询结果,并把结果中的你选择的comboBox值对应的divisionCode字段值赋给Grid中的divisionCode列,同时comboBox对应的itemCategoryCode字段值赋给Grid中的

itemCategoryCode列!

 

 

var productCategory=new dnet.base.AbstractCombo({
	 _dataProviderFields_:ItemMaster.ProductCategory$Model
	,storeUrl:"/ItemMasterManagement/getField.action?field=ProductCategory",tpl:ItemMaster.tpl
	,valueField:ItemMaster.valueField,displayField:ItemMaster.displayField
	,queryParam:ItemMaster.queryParam
	,callFromGrid:p
	,paramMapping:[{param:'brandCode',field:'brandName'}]
	,fieldMapping:[{field:'divisionCode',column:'divisionCode'},{field:'itemCategoryCode',column:'itemCategoryCode'}]
});
productCategory._createStore_();
分享到:
评论

相关推荐

    ExtJS 组件扩展

    例如,实现一个下拉树(ComboTree)组件,即通过扩展现有的ComboBox组件来满足特殊的需求。 - **特点**: - 技术导向:需要深入理解组件的工作原理、生命周期以及渲染机制。 - 代码细节多:涉及外观设计、DOM结构...

    extjs3.x combobox智能联想

    在提供的`combobox智能联想.txt`文件中,可能会包含实现上述功能的具体代码示例,包括EXTJS的配置、事件处理和可能的自定义扩展。通过阅读和理解这些代码,你可以更好地掌握EXTJS 3.x Combobox的智能联想功能,并...

    Extjs3.4.0版本 多选下拉框效果支持多选/全选/全不选

    首先,我们来看看`LovCombo.js`,这可能是一个自定义的组合框组件,扩展了ExtJS的原生ComboBox类,以实现多选功能。在ExtJS中,创建这样的组件通常涉及到以下步骤: 1. **创建一个新的类**:定义一个继承自Ext.form...

    模仿extjs风格写的jquery combobox

    标题中的“模仿extjs风格写的jquery combobox”指的是一个基于jQuery的下拉选择框组件,它的设计灵感来源于ExtJS库的ComboBox控件。ExtJS是一款功能丰富的JavaScript框架,以其强大的组件化和数据绑定机制著名,而...

    extjs多选 下拉框扩展

    总结起来,"extjs多选 下拉框扩展"是为了满足ExtJS应用中多选功能的需求,通过对原生ComboBox组件进行扩展和定制,实现了带有复选框的多选下拉框。这个扩展可能包括了新的配置项、模板修改、事件处理、数据模型、...

    无废话ExtJs 教程十[下拉列表:Combobox]

    - 阅读源码可以帮助我们了解Combobox内部的工作原理,以及如何根据需求调整和扩展功能。 6. **工具支持** - ExtJS 提供的IDE和开发工具,如Sencha Architect,可以帮助直观地设计和构建Combobox,简化开发流程。 ...

    无废话ExtJs 系统教程十九[动态复选框:RemoteCheckboxGroup]

    “RemoteCheckboxGroup”是ExtJS中的一个特定组件,它扩展了基础的CheckboxGroup类。在默认情况下,CheckboxGroup组件通常用于显示一组静态的复选框,而RemoteCheckboxGroup则增加了动态加载和更新复选框选项的功能...

    Extjs4 combogrid扩展

    在给定的“Extjs4 combogrid扩展”中,我们主要关注的是如何将传统的下拉框(combo)扩展为同时支持网格(grid)显示的功能。 标题中的“Extjs4 combogrid扩展”意味着我们要在ExtJS 4框架内,改造原有的 Combo ...

    extjs4 下拉菜单树 combobox+tree 支持单选多选

    综上所述,EXTJS4的下拉菜单树Combobox+Tree组件通过灵活的配置和扩展,可以满足多种应用场景的需求,无论是单选还是多选,都能提供优秀的用户体验。在实际开发中,根据项目需求进行适当的定制,可以大大提高应用...

    Ext带图标Combobox

    而"Ext带图标Combobox"(Ext IconCombobox)是Ext JS中的一个特色组件,它是Combobox(下拉框)与图标相结合的一种扩展形式,为用户提供了更加直观且美观的交互体验。 **1. Ext Combobox基础** 首先,我们需要了解...

    Extjs4下拉多选扩展

    在ExtJS中,下拉框(ComboBox)是一种常用的UI组件,通常用于展示可选择的列表项。然而,标准的下拉框只支持单选模式,如果需要实现多选功能,就需要进行一定的扩展。本文将深入探讨如何在ExtJS 4中实现下拉多选扩展...

    extjs4 实现下拉树并支持复选

    在EXTJS4中,实现一个下拉树(Combobox Tree)并支持多选和复选功能,主要是通过自定义组件(Ext.define)来完成的。这个组件继承自EXTJS的Picker字段(Ext.form.field.Picker),并添加了树形结构和复选功能。以下...

    combobox Ext之扩展组件多选下拉框

    本篇将重点讲解ExtJS中的一个扩展组件——多选下拉框,即“combobox”。 在ExtJS中,ComboBox是一个基本的输入组件,它结合了文本输入框和下拉列表的功能。默认情况下,ComboBox只允许用户选择一个选项。但是,通过...

    轻松搞定Extjs 带目录

    Extjs的组件系统非常丰富,包括按钮、日期选择器、ComboBox等,它们都可以通过配置实现复杂的交互逻辑。数据管理部分涉及到了Extjs对Ajax请求的封装、数据代理、读取器、存储等概念。Extjs对分页、表单验证、表单...

    Extjs6 下拉列表

    综上所述,ExtJS6的下拉列表(ComboBox)和GridCombo扩展控件提供了强大的功能和灵活性,它们可以用于创建丰富的用户界面,满足各种复杂的业务需求。理解和熟练掌握这些组件的使用,对于开发高质量的Web应用至关重要...

    extjs多选下拉框

    1. **扩展ComboBox**: 多选下拉框通常是基于EXTJS的ComboBox进行扩展,添加新的配置项和方法来支持多选。例如,可以添加一个`allowMultiple`配置项,当其值为`true`时启用多选模式。 2. **数据存储**:在多选模式下...

    Extjs4下拉树菜单ComboBoxTree支持单选和多选并且支持展开选中指定节点的通用控件

    ComboBoxTree是ExtJS4中的一个自定义组件,它结合了ComboBox(下拉框)和TreePanel(树形面板)的功能。ComboBox通常用于提供一个下拉列表供用户选择,而TreePanel则用于展示层次结构的数据。ComboBoxTree将这两者...

    extjs实现下拉框多选

    在ExtJS中,下拉框(ComboBox)是用户界面中常见的组件,通常用于单选操作。然而,通过扩展和定制,我们也可以实现下拉框的多选功能。在本篇中,我们将深入探讨如何在ExtJS中实现下拉框的多选功能。 首先,了解基本...

    extjs4.2 datetime控件

    7. **组合框(ComboBox)集成**:DateTime控件可能基于ExtJS的ComboBox组件构建,允许用户通过下拉菜单选择日期和时间,同时提供输入框供用户手动输入。 8. **验证**:控件通常包含内置的验证功能,以确保用户输入...

Global site tag (gtag.js) - Google Analytics