效果如下:
一、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 });
@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; }
先看一下数据库表:
1、树各个节点(叶子或非叶子)显示的值和实际的值分别是text和id,而且都是小写,所以sql语句中查询出的列用双引号引起来了
2、我的情况是区域分为4级(实际是3级,用字段district_type_id标识):0-全国、1-省级、2-市级、3-县级。所以县级是叶子节点,因此使用了"case when"。