ExtJs 3 自定义combotree
ExtJs 3 自定义combotree
/** * 自定义下拉树,支持初始化值时自动定位树节点。 * 还没有考虑性能问题。继承自Ext.form.ComboBox也很浪费。 * 代码中的cu.get()是自定义的异步请求方法。 * @author Linzongxue * @create_date 2011-12-13 */ Ext.ux.ComboBoxTree = Ext.extend(Ext.form.ComboBox, { //树的配置项 dataUrl: null, //获取树所有节点的url //通过id获取某个节点的id全路径的url,返回值的格式应该是:parentId1/parentId2/parentId3/../节点id //如果不设置这个值,下拉树不会自动定位节点并在初始化时显示文本 nodePathUrl: null, loader: null, root: {}, rootVisible: false, //树的选择模式 rootSelectable: false, //根节点是否可选,默认为false folderSelectable: true, //目录是否可选,默认为true leafSelectable: true, //叶子是否可选,默认为true showFullPath: false, //是否显示全路径 rootValue: undefined, //根节点的值(通常根节点的取值与普通节点的取值不一样,如果一样则不需要设置此值) //原combo类的配置项 store: new Ext.data.SimpleStore({fields:[],data:[[]]}), mode: ‘local‘, triggerAction: ‘all‘, editable: false, forceSelection: true, tree: null, //树控件,在expand方法中初始化 //private: 用于防止combo收缩,在树的事件中控制此属性值 preventCollapse: false, initComponent: function(){ this.treeId = Ext.id(); this.height = this.height || 200; this.tpl = String.format(‘<tpl for="."><div id="{0}" style="height:{1}px"></div></tpl>‘, this.treeId, this.height); Ext.ux.ComboBoxTree.superclass.initComponent.call(this); }, setValue: function(value){ if (Ext.isObject(value)){ //点击树节点时的选择 this.doSetValue(value); } else{ //只是设置一个值,从后台获取这个值的路径,并在树中选中这个节点 //console.log(value); if (!this.tree) this.initTree(); if (value === this.tree.root.id || (Ext.isDefined(this.rootValue) && value === this.rootValue)){ //根节点 this.tree.root.select(); this.doSetValue(this.root); return; } var url = this.nodePathUrl; if (!url){ this.doSetValue({id: value}); return; } cu.get(url, {id: value}).done(function(path){//从后台发起请求获取id路径 path = ‘/‘ + this.root.id + (path.indexOf(‘/‘) == 0 ? ‘‘ : ‘/‘) + path; var comboTree = this; this.tree.selectPath(path, ‘id‘, function(success, node){ comboTree.doSetValue(success ? node : null); }); }, this); } }, //private:设置值,参数value应该是一个对象 doSetValue: function(value){ var id = value ? value.id : ‘‘; var text = value ? value.text : ‘‘; if (value && (value.loader || value.attributes)){ //是树节点 var isRootNode = (value.id == this.tree.root.id); if (isRootNode && Ext.isDefined(this.rootValue)){ id = this.rootValue; } if (this.showFullPath){ text = isRootNode ? ‘/‘ : value.getPath(‘text‘).replace(‘/‘ + this.tree.root.text, ‘‘); } } this.value = id; if(this.hiddenField){ this.hiddenField.value = id; //设置表单域 } this.lastSelectionText = text; this.el.dom.value = text; //显示的值 this.fireEvent(‘select‘, this, value); }, getValue : function(){ return Ext.isDefined(this.value) ? this.value : ‘‘; }, //取得选中的树节点 getValueNode: function(){ return this.tree ? this.tree.getSelectionModel().getSelectedNode() : null; }, getText: function(){ return this.lastSelectionText || ‘‘; }, reload: function(){ if (!this.tree) return; var node = this.tree.getSelectionModel().getSelectedNode(); var path = node ? node.getPath() : null; this.tree.getLoader().load(this.tree.root, function(){ if (path) { this.tree.selectPath(path); } }, this); this.preventCollapse = true; }, //private: 根据preventCollapse属性判断是否要收缩 collapse: function(){ if (this.preventCollapse){ this.preventCollapse = false; return; } Ext.ux.ComboBoxTree.superclass.collapse.call(this); }, //private: expand : function(){ Ext.ux.ComboBoxTree.superclass.expand.call(this); if (!this.tree){ this.initTree(); } }, //private: destroy: function(){ if (this.tree && this.tree.rendered) this.tree.destroy(); Ext.form.ComboBox.superclass.destroy.call(this); }, //private initTree: function(){ if (!this.list){ //必须先初始化列表,在一开始就设置了combotree的值时尤其重要,发现这个问题花了半天时间 this.initList(); } //设置this.preventCollapse=true,防止combo收缩 var enableCollapse = function(){this.preventCollapse = false;}; //设置this.preventCollapse=false,允许combo收缩 var disableCollapse = function(){this.preventCollapse = true;}; this.tree = new Ext.tree.TreePanel({ renderTo: this.treeId, useArrows: false, autoScroll: true, height: this.height, //修复IE的bug animate: true, enableDD: false, containerScroll: true, border: false, dataUrl: this.dataUrl, loader: this.loader, root: this.root, rootVisible: this.rootVisible, // bbar:[ // ‘->‘, {text: ‘刷新‘, handler: this.reload, iconCls: ‘icon-refresh‘, scope: this} //由于宽度问题取消此功能 // ], listeners: { click: function(node){ disableCollapse(); if (node == this.tree.root){ //选中根节点 if (!this.rootSelectable) return; } else if (!node.isLeaf()){ //选中目录节点 if (!this.folderSelectable) return; } else{ //选中叶子节点 if (!this.leafSelectable) return; } //先选择节点,再设置value,让getNodeValue方法在select事件中取到正确的值 node.select(); this.setValue(node); enableCollapse(); }, //展开和收缩节点时防止combo收缩 beforeexpandnode: disableCollapse, beforecollapsenode: disableCollapse, beforeload: disableCollapse, //节点加载和展开后允许combo收缩 load: enableCollapse, expandnode: enableCollapse, scope: this } }); } }); Ext.reg(‘combotree‘, Ext.ux.ComboBoxTree); /**************** 下面是一个使用例子 ***********************/ new Ext.ux.ComboBoxTree({ fieldLabel:‘父菜单‘, hiddenName: ‘parentId‘, value: this.modifyId ? ‘‘ : this.parentMenu.id, height: 180, dataUrl: ‘sys/menu/getMenus.do‘, nodePathUrl: ‘sys/util/getEntityIdPath.do?c=sys.entity.Menu‘, root: {id:‘root‘, text:‘根菜单‘, expanded: true}, rootVisible: true, rootSelectable: true, rootValue: null, showFullPath: true, allowBlank: false, });
这个问题可以忽略了,还有个问题想请教下:
如果llowBlank设置为true,选中某个节点之后想清空值怎么办呢?
这个问题可以忽略了,还有个问题想请教下:
如果llowBlank设置为true,选中某个节点之后想清空值怎么办呢?
我的解决办法是在构造tree的时候增加一个带有清除按钮的tbar:
var combo = this; this.tree = new Ext.tree.TreePanel({ renderTo: this.treeId, useArrows: false, autoScroll: true, height: this.height, //fix IE animate: true, enableDD: false, containerScroll: true, border: false, dataUrl: this.dataUrl, [color=red]tbar: [{text:‘清空‘,xtype:‘button‘,iconCls:‘reset‘,handler:function(){combo.setValue(null);}}],[/color] loader: this.loader, root: this.root, rootVisible: this.rootVisible
还有没有更好的解决办法呢?
另外还有个问题:
获取某个节点的值时只能用 Ext.getCmp(‘comboboxtree‘).getNodeValue().id 吗?我试了getValue()和getRawValue(),均不能获取到节点的id。但是使用这个方法获取节点id有个问题,只有点击了comboBox之后,才会异步获取树,因此没有点击过comboBox的时候,Ext.getCmp(‘comboboxtree‘).getNodeValue()的值为null,所以使用Ext.getCmp(‘comboboxtree‘).getNodeValue().id之前要先判断Ext.getCmp(‘comboboxtree‘).getNodeValue()是否为null,否则会报错。
这个问题你有别的办法解决吗?
如果allowBlank设置为true,选中某个节点之后想清空值怎么办呢?
我的解决办法是在构造tree的时候增加一个带有清除按钮的tbar:
var combo = this;
this.tree = new Ext.tree.TreePanel({
renderTo: this.treeId,
useArrows: false,
autoScroll: true,
height: this.height, //fix IE
animate: true,
enableDD: false,
containerScroll: true,
border: false,
dataUrl: this.dataUrl,
tbar: [{text:‘清空‘,xtype:‘button‘,iconCls:‘reset‘,handler:function(){combo.setValue(null);}}],
loader: this.loader,
root: this.root,
rootVisible: this.rootVisible
还有没有更好的解决办法呢?
另外还有个问题:
获取某个节点的值时只能用 Ext.getCmp(‘comboboxtree‘).getNodeValue().id 吗?我试了getValue()和getRawValue(),均不能获取到节点的id。但是使用这个方法获取节点id有个问题,只有点击了comboBox之后,才会异步获取树,因此没有点击过comboBox的时候,Ext.getCmp(‘comboboxtree‘).getNodeValue()的值为null,所以使用Ext.getCmp(‘comboboxtree‘).getNodeValue().id之前要先判断Ext.getCmp(‘comboboxtree‘).getNodeValue()是否为null,否则会报错。
这个问题你有别的办法解决吗?
这个问题可以忽略了,还有个问题想请教下:
如果llowBlank设置为true,选中某个节点之后想清空值怎么办呢?
这个。。还没有考虑 ,因为才开始使用ExtJs没多久,很多应用细节还没机会去尝试。我觉得你的方法也挺好了,添加“清空”的同时顺便再加上一个“刷新”树节点的控制都不错。
在我贴代码之后又做了一些修改,但是修改后没有及时更新上来,太多事情要处理了啊。。。
你说的通过getValue()取不到值的问题,很可能是之后解决的,不用getNodeValue().id那么麻烦。。。,另外,异步发送请求的方法cu.get(...).done(...)只是对Ext.ajax.request做了简单的封装,并且添加了全局的异常处理而已。这种写法是从jquery里学过来的,我还摆脱不了一些jquery的使用习惯。
getValue()方法只是简单地返回this.value,关键是doSetValue()方法中对value的设置。现在是不是可以取到正确的值了?如果是就应该是之前的doSetValue()方法有问题,具体修改了什么地方我想不起来了。。。太久了。。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。