1:最近有這個需求,就是ext下的combo下拉是樹,網上的例子很多,封裝的也很好,基本都可以滿足下拉框下出現想要的樹,但是我的使用情況是比如在用戶編輯的時候,要把用戶已經選擇過的數值自動再賦值到下拉框內,比如之前選擇了id為5的節點,那么編輯用戶的時候combo中自動顯示這個值
2:網上發現這樣的例子不多,有一個是iteye上面寫的,地址為http://zxlaiye.iteye.com/blog/1310556。經過測試這個里面有幾個問題所在,並且有幾個作者也沒有說明白雜用,經過修改可以用了。
3:發個實例代碼:
- new Ext.ux.ComboBoxTree({
- fieldLabel : '父菜單',
- hiddenName : 'testTreeName',
- value : 11,
- height : 180,
- width : 200,
- dataUrl : PATH
- + '/do.php?mod=util&action=query_parent_department_tree',
- nodePathUrl : PATH
- + '/do.php?mod=util&action=query_department_path&id=11',
- rootVisible : false,
- rootSelectable : false,
- showFullPath : false,
- allowBlank : false,
- emptyText : '請選擇'
- })
其中hiddenName 是post過去的字段
dataUrl就是生成一般的樹的路徑了,這個都和平時一樣,不一樣的地方時多了個nodePathUrl,看這個我的例子中我給初始化的value為11,這個節點在我數據庫中對應的父親節點只推到最上的路徑分別為/root/8/7/11 也就是說這個節點從剛才的路徑利用treepanel的selectPath方法直接找到這個節點,然后把這個節點text對應到combo中,把value設置給name。之前這個問題是里面有個路徑問題不可以找到,還有個地方時一個cu的函數的封裝,cu函數就是請求nodePathUrl的。里面還有個問題是如果當前tree中沒有root節點的話是對應不到的,總之我給修整好是可以用了,大家看源代碼:
- /**
- * 自定義下拉樹,支持初始化值時自動定位樹節點。 還沒有考慮性能問題。繼承自Ext.form.ComboBox也很浪費。
- * 代碼中的cu.get()是自定義的異步請求方法。
- */
- /*
- * 例子 new Ext.ux.ComboBoxTree({ fieldLabel:'父菜單', hiddenName: 'parentId', value:
- * this.modifyId ? '' : this.parentMenu.id, height: 180, dataUrl:
- * 'sys/menu/getMenus.do', 就是獲取一般tree的url nodePathUrl:
- * 'sys/util/getEntityIdPath.do?c=sys.entity.Menu',獲取需要默認選中的那個節點的路徑parentId/parentId/.../被選中節點的id
- * root: {id:'root', text:'根菜單', expanded: true}, rootVisible: true,
- * rootSelectable: true, rootValue: null, showFullPath: true, allowBlank: false,
- * });
- */
- /**
- * @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 { // 只是設置一個值,從后台獲取這個值的路徑,並在樹中選中這個節點
- 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;
- }
- Ext.Ajax.request({
- url : url,
- async : false,
- scope : this,
- success : function(resp, opts) {
- var comboTree = this;
- path = resp.responseText;
- path = (path.indexOf('/') == 0 ? '' : '/')
- +comboTree.tree.root.id+'/'+ path;
- this.tree.selectPath(path, 'id', function(success,
- node) {
- comboTree.doSetValue(success
- ? node
- : null);
- });
- },
- faliure : function() {
- alert(3)
- }
- });
- /*
- * 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);