首先主要代码源自网络,对那些无私的奉献者表示感谢!
笔者对这些代码做了二次修改,并总结如下:
Extjs3.x版本下拉树代码:
Ext.ux.TreeCombo = Ext.extend(Ext.form.ComboBox, { constructor : function(cfg) { cfg = cfg || {}; Ext.ux.TreeCombo.superclass.constructor.call(this, Ext.apply({ maxHeight : 300, editable : false, mode : 'local', triggerAction : 'all', rootVisible : false, selectMode : 'all' }, cfg)); }, store : new Ext.data.SimpleStore({ fields : [], data : [[]] }), // 重写onViewClick,使展开树结点是不关闭下拉框 onViewClick : function(doFocus) { var index = this.view.getSelectedIndexes()[0], s = this.store, r = s.getAt(index); if (r) { this.onSelect(r, index); } if (doFocus !== false) { this.el.focus(); } }, tree : null, // 隐藏值 hiddenValue : null, getHiddenValue : function() { return this.hiddenValue; }, getValue : function() { //增加适用性,与原来combo组件一样 return this.hiddenValue; }, setHiddenValue : function(code, dispText) { this.setValue(code); Ext.form.ComboBox.superclass.setValue.call(this, dispText); this.hiddenValue = code; }, initComponent : function() { var _this = this; var tplRandomId = 'deptcombo_' + Math.floor(Math.random() * 1000) + this.tplId this.tpl = "<div style='height:" + _this.maxHeight + "px' id='" + tplRandomId + "'></div>" this.tree = new Ext.tree.TreePanel({ border : false, enableDD : false, enableDrag : false, rootVisible : _this.rootVisible || false, autoScroll : true, trackMouseOver : true, height : _this.maxHeight, lines : true, singleExpand : true, root : new Ext.tree.AsyncTreeNode({ id : _this.rootId, text : _this.rootText, iconCls:'ico-root', expanded:true, leaf : false, border : false, draggable : false, singleClickExpand : false, hide : true }), loader : new Ext.tree.TreeLoader({ nodeParameter:'ID', requestMethod:'GET', dataUrl : _this.url }) }); this.tree.on('click', function(node) { if ((_this.selectMode == 'leaf' && node.leaf == true) || _this.selectMode == 'all') { if(_this.fireEvent('beforeselect',_this,node)){ _this.fireEvent('select',_this,node); } } }); this.on('select',function(obj,node){ var dispText = node.text; var code = node.id; obj.setHiddenValue(code, dispText); obj.collapse(); }); this.on('expand', function() { this.tree.render(tplRandomId); }); Ext.ux.TreeCombo.superclass.initComponent.call(this); } }) Ext.reg("treecombo", Ext.ux.TreeCombo);
使用方法:
var treecombo=new Ext.ux.TreeCombo({ name : 'areaName', tplId : 'tree_tpl', rootVisible : true, rootText : '/', rootId:'root', url : 'getTreeData.aspx', maxHeight :300, id: 'cmbJS', allowBlank: true, selectMode:'leaf', width : '200' });
Extjs4.x版本下拉树代码一:
Ext.define('Ext.ux.TreeComboBox',{ extend : 'Ext.form.field.ComboBox', alias: 'widget.treecombo', store : new Ext.data.ArrayStore({fields:[],data:[[]]}), editable : false, listConfig : {resizable:true,minWidth:100,maxWidth:400,minHeight:200,maxHeight:400}, _idValue : null, _txtValue : null, treeObj: null, initComponent : function(){ var _this = this; this.treeObj= new Ext.tree.Panel({ border : false, id:Ext.id(), height : 380, width : 400, autoScroll : true, store : Ext.create('Ext.data.TreeStore', { fields : ['id','text','leaf'], autoLoad : false, nodeParam: 'ID', proxy: { type: 'ajax', url : _this.url }, root: { expanded: _this.expanded||false, id:_this.rootId||'root', text : _this.rootText||'/' } }) }); this.treeRenderId = Ext.id(); this.tpl = "<div id='"+this.treeRenderId+"'></div>"; this.callParent(arguments); this.on({ 'expand' : function(){ if(!this.treeObj.rendered&&this.treeObj&&!this.readOnly){ Ext.defer(function(){ this.treeObj.render(this.treeRenderId); },300,this); } } }); this.treeObj.on('itemclick',function(view,rec){ if(rec&&((_this.selectMode == 'leaf' && rec.isLeaf() == true) || _this.selectMode == 'all')){ this.setValue(this._txtValue = rec.get('text')); this._idValue = rec.get('id'); this.collapse(); _this.fireEvent('select',_this,rec); } },this); }, getValue : function(){//获取id值 return this._idValue; }, getTextValue : function(){//获取text值 return this._txtValue; }, setLocalValue : function(id,txt){//设值 this._idValue = id; this.setValue(this._txtValue = txt); }, reLoad:function(id,url){ this.treeObj.getStore().proxy.url =url; this.treeObj.setRootNode({ id:id, text:'/', expanded:true }); } });
使用方法与前面基本相同。这个版本存在很多问题,当一个界面存在两个下拉树时,其中一个下拉树在第二次下拉操作时,树不会显示,如图:
另外由于tree渲染到div上,当节点过多出现滚动条时,会显示两条滚动条,一条是div本身的,一条是treepanel的,如图:
所以此版本不采用,其中添加了一个reLoad()方法,这是由于两个下拉树需要联动才添加的。
Extjs4.x版本下拉树代码二:
Ext.define("Ext.ux.ComboTree", { extend : "Ext.form.field.Picker", alias : 'widget.combotree', requires : ["Ext.tree.Panel"], _idValue : '', _txtValue : '', initComponent : function() { this.callParent(); var self = this; var store = Ext.create('Ext.data.TreeStore', { proxy : { type : 'ajax', url : self.storeUrl }, nodeParam: 'ID', root : { id : self.rootId, text : self.rootText, expanded:self.expanded||false } }); self.picker = new Ext.tree.Panel({ id:Ext.id(), height : self.treeHeight||300, resizable:true,minWidth:100,maxWidth:400,minHeight:200,maxHeight:500, autoScroll : true, floating : true, focusOnToFront : false, shadow : true, ownerCt : this.ownerCt, useArrows : self.useArrows||true, store : store, rootVisible : true }); self.picker.on({ 'itemclick' : function(view,rec) { if(rec&&((self.selectMode == 'leaf' && rec.isLeaf() == true) || self.selectMode == 'all')){ //self.setRawValue(rec.get('id'));// 隐藏值 self._idValue = rec.get('id'); self.setValue(self._txtValue=rec.get('text'));// 显示值 self.collapse(); self.fireEvent('select',self,rec); } } }); }, // createPicker : function() { // var self = this; // var store = Ext.create('Ext.data.TreeStore', { // proxy : { // type : 'ajax', // url : self.storeUrl // }, // nodeParam: 'ID', // root : { // id : self.rootId, // text : self.rootText, // expanded:self.expanded||true // } // }); // self.picker = new Ext.tree.Panel({ // id:Ext.id(), // height : 300, // //resizable:true,minWidth:100,maxWidth:400,minHeight:200,maxHeight:400, // autoScroll : true, // floating : true, // focusOnToFront : false, // shadow : true, // ownerCt : this.ownerCt, // useArrows : self.useArrows||true, // store : store, // rootVisible : true // }); // self.picker.on({ // 'itemclick' : function(view,rec) { // if(rec&&((self.selectMode == 'leaf' && rec.isLeaf() == true) || self.selectMode == 'all')){ // //self.setRawValue(rec.get('id'));// 隐藏值 // self._idValue = rec.get('id'); // self.setValue(self._txtValue=rec.get('text'));// 显示值 // self.collapse(); // self.fireEvent('select',self,rec); // } // } // }); // return self.picker; // }, getValue : function(){//获取id值 return this._idValue; }, getTextValue : function(){//获取text值 return this._txtValue; }, reLoad:function(id,url){ var store=this.picker.getStore(); var root=this.picker.getRootNode(); store.proxy.url =url; root.set('id',id); store.load(); }, alignPicker : function() { var me = this, picker, isAbove, aboveSfx = '-above'; if (this.isExpanded) { picker = me.getPicker(); if (me.matchFieldWidth) { picker.setWidth(me.bodyEl.getWidth()); } if (picker.isFloating()) { picker.alignTo(me.inputEl, "", me.pickerOffset); isAbove = picker.el.getY() < me.inputEl.getY(); me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls+ aboveSfx); picker.el[isAbove ? 'addCls' : 'removeCls'](picker.baseCls+ aboveSfx); } } } });
此版本解决了上述两大问题,其中注解的部分为原作者代码,使用createPicker存在一个问题,必须点击下拉操作后,treepanel才会进行渲染,那么数据联动也就谈不上了(需要联动的tree没有渲染,如何进行数据加载?),所以笔者移到initComponent下执行,另外也解决了resize的问题。
使用方法:
var treecombo=new Ext.ux.ComboTree({ fieldLabel: 'Test', labelWidth: 60, rootText : '/', rootId:'root', expanded:true, storeUrl : 'getTreeData.aspx', id: 'cmbJS', selectMode:'leaf', treeHeight:300, width : 200 });
到此,Extjs4.1的下拉树完美了,世界太平了!