combotree的总结(这个好)

1:最近有这个需求,就是ext下的combo下拉是树,网上的例子很多,封装的也很好,基本都可以满足下拉框下出现想要的树,但是我的使用情况是比如在用户编辑的时候,要把用户已经选择过的数值自动再赋值到下拉框内,比如之前选择了id为5的节点,那么编辑用户的时候combo中自动显示这个值

2:网上发现这样的例子不多,有一个是iteye上面写的,地址为http://zxlaiye.iteye.com/blog/1310556。经过测试这个里面有几个问题所在,并且有几个作者也没有说明白杂用,经过修改可以用了。

3:发个实例代码:

[javascript] view plaincopyprint?
  1. new Ext.ux.ComboBoxTree({  
  2.      fieldLabel : '父菜单',  
  3.      hiddenName : 'testTreeName',  
  4.      value : 11,  
  5.      height : 180,  
  6.      width : 200,  
  7.      dataUrl : PATH  
  8.        + '/do.php?mod=util&action=query_parent_department_tree',  
  9.      nodePathUrl : PATH  
  10.        + '/do.php?mod=util&action=query_department_path&id=11',  
  11.      rootVisible : false,  
  12.      rootSelectable : false,  
  13.      showFullPath : false,  
  14.      allowBlank : false,  
  15.      emptyText : '请选择'  
  16.     })  

其中hiddenName 是post过去的字段

dataUrl就是生成一般的树的路径了,这个都和平时一样,不一样的地方时多了个nodePathUrl,看这个我的例子中我给初始化的value为11,这个节点在我数据库中对应的父亲节点只推到最上的路径分别为/root/8/7/11  也就是说这个节点从刚才的路径利用treepanel的selectPath方法直接找到这个节点,然后把这个节点text对应到combo中,把value设置给name。之前这个问题是里面有个路径问题不可以找到,还有个地方时一个cu的函数的封装,cu函数就是请求nodePathUrl的。里面还有个问题是如果当前tree中没有root节点的话是对应不到的,总之我给修整好是可以用了,大家看源代码:

  1. /**  
  2.  * 自定义下拉树,支持初始化值时自动定位树节点。 还没有考虑性能问题。继承自Ext.form.ComboBox也很浪费。  
  3.  * 代码中的cu.get()是自定义的异步请求方法。  
  4.  */  
  5. /*  
  6.  * 例子 new Ext.ux.ComboBoxTree({ fieldLabel:'父菜单', hiddenName: 'parentId', value:  
  7.  * this.modifyId ? '' : this.parentMenu.id, height: 180, dataUrl:  
  8.  * 'sys/menu/getMenus.do', 就是获取一般tree的url nodePathUrl:  
  9.  * 'sys/util/getEntityIdPath.do?c=sys.entity.Menu',获取需要默认选中的那个节点的路径parentId/parentId/.../被选中节点的id  
  10.  * root: {id:'root', text:'根菜单', expanded: true}, rootVisible: true,  
  11.  * rootSelectable: true, rootValue: null, showFullPath: true, allowBlank: false,  
  12.  * });  
  13.  */  
  14. /**  
  15.  * @author Linzongxue  
  16.  * @create_date 2011-12-13  
  17.  */  
  18. Ext.ux.ComboBoxTree = Ext.extend(Ext.form.ComboBox, {  
  19.     // 树的配置项  
  20.     dataUrl : null, // 获取树所有节点的url  
  21.     // 通过id获取某个节点的id全路径的url,返回值的格式应该是:parentId1/parentId2/parentId3/../节点id  
  22.     // 如果不设置这个值,下拉树不会自动定位节点并在初始化时显示文本  
  23.     nodePathUrl : null,  
  24.     loader : null,  
  25.     root : {},  
  26.     rootVisible : false,  
  27.     // 树的选择模式  
  28.     rootSelectable : false, // 根节点是否可选,默认为false  
  29.     folderSelectable : true, // 目录是否可选,默认为true  
  30.     leafSelectable : true, // 叶子是否可选,默认为true  
  31.     showFullPath : false, // 是否显示全路径  
  32.     rootValue : undefined, // 根节点的值(通常根节点的取值与普通节点的取值不一样,如果一样则不需要设置此值)  
  33.     // 原combo类的配置项  
  34.     store : new Ext.data.SimpleStore({  
  35.                 fields : [],  
  36.                 data : [[]]  
  37.             }),  
  38.     mode : 'local',  
  39.     triggerAction : 'all',  
  40.     editable : false,  
  41.     forceSelection : true,  
  42.     tree : null, // 树控件,在expand方法中初始化  
  43.     // private: 用于防止combo收缩,在树的事件中控制此属性值  
  44.     preventCollapse : false,  
  45.   
  46.     initComponent : function() {  
  47.         this.treeId = Ext.id();  
  48.         this.height = this.height || 200;  
  49.         this.tpl = String.format(  
  50.                 '<tpl for="."><div id="{0}" style="height:{1}px"></div></tpl>',  
  51.                 this.treeId, this.height);  
  52.         Ext.ux.ComboBoxTree.superclass.initComponent.call(this);  
  53.     },  
  54.     setValue : function(value) {  
  55.         if (Ext.isObject(value)) { // 点击树节点时的选择  
  56.             this.doSetValue(value);  
  57.         } else { // 只是设置一个值,从后台获取这个值的路径,并在树中选中这个节点  
  58.             if (!this.tree)  
  59.                 this.initTree();  
  60.   
  61.             if (value === this.tree.root.id  
  62.                     || (Ext.isDefined(this.rootValue) && value === this.rootValue)) { // 根节点  
  63.                 this.tree.root.select();  
  64.                 this.doSetValue(this.root);  
  65.                 return;  
  66.             }  
  67.             var url = this.nodePathUrl;  
  68.             if (!url) {  
  69.                 this.doSetValue({  
  70.                             id : value  
  71.                         });  
  72.                 return;  
  73.             }  
  74.             Ext.Ajax.request({  
  75.                         url : url,  
  76.                         async : false,  
  77.                         scope : this,  
  78.                         success : function(resp, opts) {  
  79.                             var comboTree = this;  
  80.                             path = resp.responseText;  
  81.                             path = (path.indexOf('/') == 0 ? '' : '/')  
  82.                                     +comboTree.tree.root.id+'/'+ path;  
  83.                             this.tree.selectPath(path, 'id', function(success,  
  84.                                             node) {  
  85.                                         comboTree.doSetValue(success  
  86.                                                 ? node  
  87.                                                 : null);  
  88.                                     });  
  89.                         },  
  90.                         faliure : function() {  
  91.                             alert(3)  
  92.                         }  
  93.                     });  
  94.             /*  
  95.              * cu.get(url, {id: value}).done(function(path){//从后台发起请求获取id路径 path =  
  96.              * '/' + this.root.id + (path.indexOf('/') == 0 ? '' : '/') + path;  
  97.              * var comboTree = this; this.tree.selectPath(path, 'id',  
  98.              * function(success, node){ comboTree.doSetValue(success ? node :  
  99.              * null); }); }, this);  
  100.              */  
  101.         }  
  102.     },  
  103.     // private:设置值,参数value应该是一个对象  
  104.     doSetValue : function(value) {  
  105.         var id = value ? value.id : '';  
  106.         var text = value ? value.text : '';  
  107.         if (value && (value.loader || value.attributes)) { // 是树节点  
  108.             var isRootNode = (value.id == this.tree.root.id);  
  109.             if (isRootNode && Ext.isDefined(this.rootValue)) {  
  110.                 id = this.rootValue;  
  111.             }  
  112.             if (this.showFullPath) {  
  113.                 text = isRootNode ? '/' : value.getPath('text').replace(  
  114.                         '/' + this.tree.root.text, '');  
  115.             }  
  116.         }  
  117.         this.value = id;  
  118.         if (this.hiddenField) {  
  119.             this.hiddenField.value = id; // 设置表单域  
  120.         }  
  121.         this.lastSelectionText = text;  
  122.         this.el.dom.value = text; // 显示的值  
  123.         this.fireEvent('select', this, value);  
  124.     },  
  125.     getValue : function() {  
  126.         return Ext.isDefined(this.value) ? this.value : '';  
  127.     },  
  128.     // 取得选中的树节点  
  129.     getValueNode : function() {  
  130.         return this.tree  
  131.                 ? this.tree.getSelectionModel().getSelectedNode()  
  132.                 : null;  
  133.     },  
  134.     getText : function() {  
  135.         return this.lastSelectionText || '';  
  136.     },  
  137.     reload : function() {  
  138.         if (!this.tree)  
  139.             return;  
  140.         var node = this.tree.getSelectionModel().getSelectedNode();  
  141.         var path = node ? node.getPath() : null;  
  142.         this.tree.getLoader().load(this.tree.root, function() {  
  143.                     if (path) {  
  144.                         this.tree.selectPath(path);  
  145.                     }  
  146.                 }, this);  
  147.         this.preventCollapse = true;  
  148.     },  
  149.     // private: 根据preventCollapse属性判断是否要收缩  
  150.     collapse : function() {  
  151.         if (this.preventCollapse) {  
  152.             this.preventCollapse = false;  
  153.             return;  
  154.         }  
  155.         Ext.ux.ComboBoxTree.superclass.collapse.call(this);  
  156.     },  
  157.     // private:  
  158.     expand : function() {  
  159.         Ext.ux.ComboBoxTree.superclass.expand.call(this);  
  160.         if (!this.tree) {  
  161.             this.initTree();  
  162.         }  
  163.     },  
  164.     // private:  
  165.     destroy : function() {  
  166.         if (this.tree && this.tree.rendered)  
  167.             this.tree.destroy();  
  168.         Ext.form.ComboBox.superclass.destroy.call(this);  
  169.     },  
  170.     // private  
  171.     initTree : function() {  
  172.         if (!this.list) { // 必须先初始化列表,在一开始就设置了combotree的值时尤其重要,发现这个问题花了半天时间  
  173.             this.initList();  
  174.         }  
  175.         // 设置this.preventCollapse=true,防止combo收缩  
  176.         var enableCollapse = function() {  
  177.             this.preventCollapse = false;  
  178.         };  
  179.         // 设置this.preventCollapse=false,允许combo收缩  
  180.         var disableCollapse = function() {  
  181.             this.preventCollapse = true;  
  182.         };  
  183.         this.tree = new Ext.tree.TreePanel({  
  184.                     renderTo : this.treeId,  
  185.                     useArrows : false,  
  186.                     autoScroll : true,  
  187.                     height : this.height, // 修复IE的bug  
  188.                     animate : true,  
  189.                     enableDD : false,  
  190.                     containerScroll : true,  
  191.                     border : false,  
  192.                     dataUrl : this.dataUrl,  
  193.                     loader : this.loader,  
  194.                     root : this.root,  
  195.                     rootVisible : this.rootVisible,  
  196.                     // bbar:[  
  197.                     // '->', {text: '刷新', handler: this.reload, iconCls:  
  198.                     // 'icon-refresh', scope: this} //由于宽度问题取消此功能  
  199.                     // ],  
  200.                     listeners : {  
  201.                         click : function(node) {  
  202.                             disableCollapse();  
  203.                             if (node == this.tree.root) { // 选中根节点  
  204.                                 if (!this.rootSelectable)  
  205.                                     return;  
  206.                             } else if (!node.isLeaf()) { // 选中目录节点  
  207.                                 if (!this.folderSelectable)  
  208.                                     return;  
  209.                             } else { // 选中叶子节点  
  210.                                 if (!this.leafSelectable)  
  211.                                     return;  
  212.                             }  
  213.                             // 先选择节点,再设置value,让getNodeValue方法在select事件中取到正确的值  
  214.                             node.select();  
  215.                             this.setValue(node);  
  216.                             enableCollapse();  
  217.                         },  
  218.                         // 展开和收缩节点时防止combo收缩  
  219.                         beforeexpandnode : disableCollapse,  
  220.                         beforecollapsenode : disableCollapse,  
  221.                         beforeload : disableCollapse,  
  222.                         // 节点加载和展开后允许combo收缩  
  223.                         load : enableCollapse,  
  224.                         expandnode : enableCollapse,  
  225.                         scope : this  
  226.                     }  
  227.                 });  
  228.     }  
  229. });  
  230. Ext.reg('combotree', Ext.ux.ComboBoxTree); 
原文地址:https://www.cnblogs.com/zhwl/p/3852769.html