效果如下:
一、areaTree.js
/**
* 下拉树ComboBoxTree
*
* @extend Ext.form.ComboBox
* @xtype 'combotree'
*/
ComboBoxTree = Ext.extend(Ext.form.ComboBox, {
/**
* 作为隐藏域的name属性
*/
passName : 'id',
/**
* 是否允许非叶子结点的单击事件
*
* @default false
*/
allowUnLeafClick : true,
/**
* 树显示的高度,默认为180
*/
treeHeight : 180,
store : new Ext.data.SimpleStore({
fields : [],
data : [[]]
}),
editable : false, // 禁止手写及联想功能
mode : 'local',
triggerAction : 'all',
selectedClass : '',
onSelect : Ext.emptyFn,
emptyText : '请选择...',
/**
* 清空值
*/
clearValue : function() {
if (this.passField)
this.passField.value = '';
this.setRawValue('');
},
/**
* 设置传值
*
* @param passvalue
*/
setPassValue : function(passvalue) {
if (this.passField)
this.passField.value = passvalue;
},
/**
* 下拉树被点击事件添加一处理方法
*
* @param node
*/
onTreeSelected : function(node) {
},
getValue : function() {
return this.passField.value;
},
/**
* 树的单击事件处理
*
* @param node,event
*/
treeClk : function(node, e) {
if (!node.isLeaf() && !this.allowUnLeafClick) {
e.stopEvent();// 非叶子节点则不触发
return;
}
this.isLeaf.value = node.isLeaf();
this.setValue(node.text);// 设置option值
this.collapse();// 隐藏option列表
if (this.passField)
this.passField.value = node.id;// 以树的节点ID传递
// 选中树节点后的触发事件
this.fireEvent('treeselected', node);
},
/**
* 初始化 Init
*/
initComponent : function() {
ComboBoxTree.superclass.initComponent.call(this);
this.tree.autoScroll = true;
this.tree.height = this.treeHeight;
this.tree.containerScroll = false;
this.tplId = Ext.id();
// overflow:auto"
this.tpl = '<div id="' + this.tplId + '" style="height:' + this.treeHeight + 'px";overflow:hidden;"></div>';
/**
* 添加treeselected事件, 选中树节点会激发这个事 件, 参数为树的节点
*/
this.addEvents('treeselected');
// this.on('treeselected',this.onTreeSelected,this);
},
/**
* 事件监听器 Listener
*/
listeners : {
'expand' : {
fn : function() {
if (!this.tree.rendered && this.tplId)
this.tree.render(this.tplId);
this.tree.show();
},
single : true
},
'render' : {
fn : function() {
this.tree.on('click', this.treeClk, this);
/**
* 创建隐藏输入域<input /> 并将其dom传给passField
*/
if (this.passName) {
this.passField = this.getEl().insertSibling({
tag : 'input',
type : 'hidden',
name : this.passName,
id : this.passName
}, 'before', true);
}
this.passField.value = this.passValue !== undefined ? this.passValue : (this.value !== undefined ? this.value : '');
this.el.dom.removeAttribute('name');
this.isLeaf = this.getEl().insertSibling({
tag : 'input',
type : 'hidden',
name : 'isleaf',
id : 'isleaf'
}, 'before', true);
// this.isLeaf.value = this.isleaf;
}
},
'beforedestroy' : {
fn : function(cmp) {
this.purgeListeners();
this.tree.purgeListeners();
}
}
},
//该方法是重写ext内部的方法,目的是防止点击加号后隐藏树;
//会隐藏是因为comboBox控件中的某一项被点击后本身会隐藏起来。
onViewClick : function(doFocus) {
var index = this.view.getSelectedIndexes()[0], s = this.store, r = s.getAt(index);
if (r) {
this.onSelect(r, index);
} else if (s.getCount() === 0) {
this.collapse();
}
if (doFocus !== false) {
this.el.focus();
}
}
});
/**
* 将ComboBoxTree注册为Ext的组件,以便使用 Ext的延迟渲染机制,xtype:'combotree'
*/
Ext.reg('combotree', ComboBoxTree);
二、引用上面的,下面是需要用到这个控件加载数据
var areaTree = new Ext.tree.TreePanel({
rootVisible : false,
root : new Ext.tree.AsyncTreeNode({
id : '0',
text : '全国',
expanded : true,
loader : new Ext.tree.TreeLoader({
dataUrl : 'getAreaTree' //查询数据的方法指向
})
})
});
var areaTreeCombo = new ComboBoxTree({
fieldLabel : '区域',
id : 'areaQuery',
autoHeight : true,
emptyText : '请选择...',
passName : 'treecombo',
// allowUnLeafClick:false,//只允许选择叶子
treeHeight : 200,
tree : areaTree
});
三、getAreaTree方法,数据源
@RequestMapping(value="/getAreaTree")
@ResponseBody
public List<Map<String,Object>> getAreaTree(String node) {
String sql = "select t.district_id as \"id\", t.district_name as \"text\", (case when t.district_type_id = 3 then 'true' else '' end) \"leaf\"" +
" from pf_district_area t where t.parent_district_id=" + node;
logger.info("SQL " + sql);
List<Map<String,Object>> list = jdbcTemplate.queryForList(sql);
return list;
}
对sql语句的解释:
先看一下数据库表:
1、树各个节点(叶子或非叶子)显示的值和实际的值分别是text和id,而且都是小写,所以sql语句中查询出的列用双引号引起来了
2、我的情况是区域分为4级(实际是3级,用字段district_type_id标识):0-全国、1-省级、2-市级、3-县级。所以县级是叶子节点,因此使用了"case when"。