首先主要代码源自网络,对那些无私的奉献者表示感谢!
笔者对这些代码做了二次修改,并总结如下:
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的下拉树完美了,世界太平了!
作者:
kunoy
申明:作者写博是为了总结经验,和交流学习之用。
如需转载,请尽量保留此申明,并在文章页面明显位置给出原文连接。谢谢!
如需转载,请尽量保留此申明,并在文章页面明显位置给出原文连接。谢谢!