最近項目開發要求用樹形列表顯示多列數據,結構例如:
研發部
|--張三 男 25歲
|--李四 女 25歲
項目部
|--王二 男 18歲
接到任務后,首先想到的時Ext的Tree控件,但Ext.Tree.Treepanel只能顯示單列數據,也就是說無法顯示 "性別"和"年齡"這兩個字段。
到網上查了相關資料后發現Ext拓展的TreeGrid是Table數,可以滿足自己的需求,但TreeGrid在用的時候遇到了一個棘手的問題:沒有原生TreeNode的CheckBox功能。
查了半天資料也到了比較完美的解決方案:
一、解決方法:
打開TreeGridNodeUI.js文件,將下面記為綠色的代碼插入到相應位置,並保存文件。
1 /*! 2 * Ext JS Library 3.4 3 * Copyright(c) 2006-2010 Sencha Inc. 4 * licensing@sencha.com 5 * http://www.sencha.com/license 6 */ 7 /** 8 * @class Ext.ux.tree.TreeGridNodeUI 9 * @extends Ext.tree.TreeNodeUI 10 */ 11 Ext.ux.tree.TreeGridNodeUI = Ext.extend(Ext.tree.TreeNodeUI, { 12 isTreeGridNodeUI: true, 13 14 renderElements : function(n, a, targetNode, bulkRender){ 15 var t = n.getOwnerTree(), 16 cols = t.columns, 17 c = cols[0], 18 i, buf, len; 19 20 this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : ''; 21 22 var cb = Ext.isBoolean(a.checked); 23 buf = [ 24 '<tbody class="x-tree-node">', 25 '<tr ext:tree-node-id="', n.id ,'" class="x-tree-node-el x-tree-node-leaf ', a.cls, '">', 26 '<td class="x-treegrid-col">', 27 '<span class="x-tree-node-indent">', this.indentMarkup, "</span>", 28 '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />', 29 '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon', (a.icon ? " x-tree-node-inline-icon" : ""), (a.iconCls ? " "+a.iconCls : ""), '" unselectable="on" />', 30 cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '', 31 '<a hidefocus="on" class="x-tree-node-anchor" href="', a.href ? a.href : '#', '" tabIndex="1" ', 32 a.hrefTarget ? ' target="'+a.hrefTarget+'"' : '', '>', 33 '<span unselectable="on">', 34 (c.tpl ? c.tpl.apply(a) : a[c.dataIndex] || c.text), 35 '</span></a>', 36 '</td>' 37 ]; 38 39 for(i = 1, len = cols.length; i < len; i++){ 40 c = cols[i]; 41 buf.push( 42 '<td class="x-treegrid-col ', (c.cls ? c.cls : ''), '">', 43 '<div unselectable="on" class="x-treegrid-text"', (c.align ? ' style="text-align: ' + c.align + ';"' : ''), '>', 44 (c.tpl ? c.tpl.apply(a) : a[c.dataIndex]), 45 '</div>', 46 '</td>' 47 ); 48 } 49 50 buf.push( 51 '</tr><tr class="x-tree-node-ct"><td colspan="', cols.length, '">', 52 '<table class="x-treegrid-node-ct-table" cellpadding="0" cellspacing="0" style="table-layout: fixed; display: none; width: ', t.innerCt.getWidth() ,'px;"><colgroup>' 53 ); 54 for(i = 0, len = cols.length; i<len; i++) { 55 buf.push('<col style="width: ', (cols[i].hidden ? 0 : cols[i].width) ,'px;" />'); 56 } 57 buf.push('</colgroup></table></td></tr></tbody>'); 58 59 if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){ 60 this.wrap = Ext.DomHelper.insertHtml("beforeBegin", n.nextSibling.ui.getEl(), buf.join('')); 61 }else{ 62 this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join('')); 63 } 64 65 this.elNode = this.wrap.childNodes[0]; 66 this.ctNode = this.wrap.childNodes[1].firstChild.firstChild; 67 var cs = this.elNode.firstChild.childNodes; 68 69 this.indentNode = cs[0]; 70 this.ecNode = cs[1]; 71 this.iconNode = cs[2]; 72 73 if (cb) { 74 this.checkbox = cs[3]; 75 this.anchor = cs[4]; 76 this.textNode = cs[4].firstChild; 77 } else { 78 this.anchor = cs[3]; 79 this.textNode = cs[3].firstChild; 80 } 81 }, 82 83 // private 84 animExpand : function(cb){ 85 this.ctNode.style.display = ""; 86 Ext.ux.tree.TreeGridNodeUI.superclass.animExpand.call(this, cb); 87 } 88 }); 89 90 Ext.ux.tree.TreeGridRootNodeUI = Ext.extend(Ext.tree.TreeNodeUI, { 91 isTreeGridNodeUI: true, 92 93 // private 94 render : function(){ 95 if(!this.rendered){ 96 this.wrap = this.ctNode = this.node.ownerTree.innerCt.dom; 97 this.node.expanded = true; 98 } 99 100 if(Ext.isWebKit) { 101 // weird table-layout: fixed issue in webkit 102 var ct = this.ctNode; 103 ct.style.tableLayout = null; 104 (function() { 105 ct.style.tableLayout = 'fixed'; 106 }).defer(1); 107 } 108 }, 109 110 destroy : function(){ 111 if(this.elNode){ 112 Ext.dd.Registry.unregister(this.elNode.id); 113 } 114 delete this.node; 115 }, 116 117 collapse : Ext.emptyFn, 118 expand : Ext.emptyFn 119 });
二、使用方法:
PS:TreeGrid的CheckBox使用方法與Ext.Tree.Treepanel的CheckBox使用方法完全一樣,包括數據生成和前台的方法、屬性、事件。
1、添加CheckBox(生成Json字符串時在Item中加入checked屬性即可,注意區分大小寫)
例如:
1 { [id:'1',text:'張三'], 2 3 [id:'0',text:'張三',checked:true], 4 5 [id:'1',text:'張三',checked:false] }
以上我列出了三種情況:
①不使用CheckBox,不需要加"checked"屬性,因為TreeNode認為,如果有checked屬性就會在節點中自動增加CheckBox;
②使用CheckBox並默認為勾選狀態,需要添加"checked"屬性,並設置值為"false";
③使用CheckBox並默認為不勾選狀態,需要添加"checked"屬性,並設置值為"true";
2、在js中獲取CheckBox選中狀態的值。
直接調用TreeNode的atributes.checked方法即可。
例如:
1 TreeGrid.root.childNodes[0].attributes.checked
3、在js中設置CheckBox狀態為選中或取消選中。
這里需要分兩步
①設置CheckBox為選中或取消。
②設置checked屬性:因為TreeNode不會自動設置TreeNode的TreeNode.attributes.checked屬性。
下面請看代碼:第一行是設置Checkbox的選中狀態
第二行是設置checked屬性。
1 TreeGrid.root.childNodes[0].getUI().checkbox.checked = true; 2 TreeGrid.root.childNodes[0].attributes.checked=true;
這是第一次寫博客,排版不是很專業,請大家包涵一下,還在加班中,要發布程序了,就到此結束吧。。。有問題可以跟帖,我回答復。
下次會寫關於Ext TreeGrid 左右相互拖拽(拖動)貨單相拖拽的相關操作文章。
下面是帶CheckBox的TreeGrid文件包,大家可以下載了直接用。