进阶篇(6)-ExtJs中的TreePanel详解
- 格式:ppt
- 大小:1.68 MB
- 文档页数:42
第八章 Tree(树)层级数据是很多开发者所熟知的。
“根-枝-叶”的结构是很多用户界面的最基本的特征。
windows的资源管理器中就展示了一个包含子节点、父节点和更深层次节点的树,以此来展示文件夹和文件的层级关系。
Ext.tree允许开发者只通过使用几行代码就展示出这样的层级数据,并且提供了大量的简单的配置来适应更广泛的需求。
虽然ExtJS默认的tree节点是file和folder图标样式,但是它不会仅仅将树局限于文件系统这一概念里。
每一项的图标和文字,或者树中的节点,都可以根据动态或者静态的数据来改变——不需要自己写代码。
想想,我们如果希望建立一个用户组,为每个用户展示它们自己的图标;又或者希望展示一画廊的图片并且在图标中预览这些图片。
ExtJS可以帮助我们实现这些愿望,而且十分简单。
种植未来:(作者使用培育植物的过程形象化地比喻建立tree的过程)ExtJS的tree不会关心你显示什么样的数据,因为它可以随心所欲地处理任何你碰到情况。
数据可以实现就加载好,又或者从逻辑上进行分割。
你可以直接在tree中编辑数据,改变标签和位置,或者你可以修改整棵树的样子以及每个节点的外观,一切都为了用户体验。
ExtJS的tree是从Component模型上建立起来的。
Component是真个ExtJS框架的基础。
也就是说,开发者从熟悉的Component的系统中获得了便利,因为用户能偶得到一种统一的和集成的体验效果。
你同样可以保证tree和应用中的其他组件天衣无缝地工作在一起。
从小种子开始:在这章里,你可以看到如何使用很少的代码建立一棵树。
我们还将讨论利用唯一的数据结构来产生一个tree,以及如何使用数据可以让你操控重要的配置项。
ExtJS 树提供了很多高级支持,例如排序、拖拽等。
但是,如果你想要真的定制一棵,我们还需要探索如何重写或者扩展configure options(配置项目)、methods(方法)、events(事件)的方法。
1.Ext.create('Ext.tree.Panel', {2. renderTo: Ext.getBody(),3. title: 'Simple Tree',4. width: 150,5. height: 150,6. root: {7. text: 'Root',8. expanded: true,9. children: [10. {11. text: 'Child 1',12. leaf: true13. },14. {15. text: 'Child 2',16. leaf: true17. },18. {19. text: 'Child 3',20. expanded: true,21. children: [22. {23. text: 'Grandchild',24. leaf: true25. }26. ]27. }28. ]29. }30.});此树面板渲染到document.body元素上。
我们把定义的根节点(The Root Node)自动扩张开来,这是默认的情况。
根节点有三个子节点,其中前两个是leaf 节点,表示他们下面没有任何子节点(children)了(终结了)。
第三个节点是一个叶子节点,已经有一个child 的叶节点(one child leaf node)。
text 属性是节点的显示的文本。
可打开例子看看效果如何。
This Tree Panel renders itself to the document body. We defined a root node that is expanded by default. The root node has three children, the first two of which are leaf nodes which means they cannot have any children. The third node is not a leaf node and has has one child leaf node. The text property is used as the node's text label.See Simple Tree for a live demo.树面板的数据存储在TreeStore。
Ext TreePanel实现单选等功能在ext1.x里,树是没有checkbox的, 幸好在2.X版本里提供了这个功能, 在许多应用里, 带有checkbox的树使用还是很常见的Ext2.X提供了简单的checkbox实现,但对于一些复杂的需求,如: 级联多选(选中父结点,自选中其所有子结点和所有父结点) , 单选等等, Ext2.X并没有帮我们实还有最难解决的情况, 当树是异步的时候, 要想级联多选, 实现起来有些难度在此, 通过对Ext.tree.TreeNodeUI进行扩展,这些问题都得到很好的解决对Ext.tree.TreeNodeUI 进行checkbox功能的扩展,后台返回的结点信息不用非要包含checked属性扩展的功能点有:一、支持只对树的叶子进行选择只有当返回的树结点属性leaf = true 时,结点才有checkbox可选使用时,只需在声明树时,加上属性onlyLeafCheckable: true 既可,默认是false二、支持对树的单选只允许选择一个结点使用时,只需在声明树时,加上属性 checkModel: "single" 既可三、支持对树的级联多选当选择结点时,自动选择该结点下的所有子结点,或该结点的所有父结点(根结点除外),特别是支持异步,当子结点还没显示时,会从后台取得子结点,然后将其选中/取消选中使用时,只需在声明树时,加上属性 checkModel: "cascade" 或"parentCascade"或"childCascade"既可cascade :级联选中所有父结点和子结点parentCascade :级联选中所有父结点childCascade :级联选中所有子结点四、添加"check"事件该事件会在树结点的checkbox发生改变时触发使用时,只需给树注册事件,如:tree.on("check",function(node,checked){...});默认情况下,checkModel为'multiple',也就是多选;onlyLeafCheckable为false,所有结点都可选使用方法:在loader里加上baseAttrs:{uiProvider:Ext.ux.TreeCheckNodeUI} 既可.例如:Js代码Java代码1.var tree = new Ext.tree.TreePanel({2.el:'tree-ct',3.width:568,4.height:300,5.checkModel: 'cascade', // 对树的级联多选6.onlyLeafCheckable: false,//对树所有结点都可选7.animate: false,8.rootVisible: false,9.autoScroll:true,10.dwrCall:Tmplt.getTmpltTree,11.baseAttrs: { uiProvider: Ext.ux.TreeCheckNodeUI } //添加uiProvider属性12.}),13.root: new Ext.tree.AsyncTreeNode({ id:'0' })14.});15.tree.on("check",function(node,checked){alert(node.tex t+" = "+checked)}); //注册"check"事件16.tree.render();17.18.var tree = new Ext.tree.TreePanel({19.el:'tree-ct',20.width:568,21.height:300,22.checkModel: 'cascade', //对树的级联多选23.onlyLeafCheckable: false,//对树所有结点都可选24.animate: false,25.rootVisible: false,26.autoScroll:true,27.loader: new Ext.tree.DWRTreeLoader({28.dwrCall:Tmplt.getTmpltTree,29.baseAttrs: { uiProvider: Ext.ux.TreeCheckNodeUI }//添加uiProvider属性30.}),31.root: new Ext.tree.AsyncTreeNode({ id:'0' })32.});33.tree.on("check",function(node,checked){alert(node.tex t+" = "+checked)}); //注册"check"事件34.tree.render();需要注意的是, 使用例子里的Tree 使用了Ext.tree.DWRTreeLoader这个扩展类,用来加载后台树结点,这和使用其它的loader没有区别的,如果您使用其它的loader, 同样加上baseAttrs: { uiProvider: Ext.ux.TreeCheckNodeUI } 就行了Java代码1.实现单选功能:2.this.on('checkchange',this.check,this);3.getNodes:function(treePanel){4.var startNode = treePanel.getRootNode();5.var r = [];6.var f = function(){7.r.push(this);8.};9.10.startNode.cascade(f);11.return r;12.},13.check : function(node,bool) {14.if(!bool){15.return;16.}17.if(this.checkModel=='single'){18.var nodes =this.getNodes(this);19.if(nodes && nodes.length>0){20.for(var i=0,len=nodes.length;i21.if(nodes[i].id!=node.id){22.if(nodes[i].getUI().checkbox){23.nodes[i].getUI().checkbox.checked = false;24.nodes[i].attributes.checked=false;25.}26.}27.}28.}29.}30.}。
extjsext.tree.panel添加监听事件EXTJS的树,如下⽅式添加事件,可以响应选择改变、单击,但双击没有响应。
⽽且在选择改变时,同时也会触发单击事件。
问题出在哪⾥?var treestore = Ext.create('Ext.data.TreeStore', {2 root: {3 text:"集团",4 id: 'org01',5 checked: true,6 expanded: true,7 children: [8 { text: "华南区", id: 'org02', expanded: true},9 { text: "华东区", id: 'org03', expanded: true, children: [10 { text: "江苏", id: 'org031', leaf: true},11 { text: "浙江", id: 'org032', leaf: true}12 ] },13 { text: "华北区", id: 'org04', expanded: true}14 ]15 }16 });1718 Ext.define('MyApp.Examples.TreeDemo', {19 extend: 'Ext.panel.Panel',2021 height: 465,22 width: 653,23 title: 'My Panel',2425 initComponent: function() {26var me = this;2728 Ext.applyIf(me, {29 items: [30 {31 xtype: 'treepanel',32 height: 430,33 width: 200,34 autoScroll:true,35 animate:true,36 id: 'treeOrg',3738//默认根⽬录显⽰39 rootVisible:true,40 border:false,41 animate:true,42 store: treestore,43 lines:true,44 enableDD:true,45 containerScroll:true,464748 listeners: {4950 itemdbclick:{51 fn: function(view, record, item, index, e,obj){52 alert('dbclick');e.stopEvent;53 },54 scope: this55 }56 ,57 itemclick: {58 fn: function(view, record, item, index, e,obj){59 alert(record.data.id+':'+record.data.text);60 e.stopEvent;61 },62 scope: this63 },64 checkchange: {65 fn: function(node,checked,obj) {66 alert('checkchange');676869 }70 }71 }7273 }74 ]75 });7677 me.callParent(arguments);78 }7980 });1。
/SanMaoSpace/archive/2013/02/04/2892 173.htmlExt Js简单Tree创建及其异步加载对于Ext Js的树的使用也是比较多的,本篇分享简单的Tree的创建及其树的异步加载处理。
1.简单TreePanel的创建function creatTree() {//创建简单的树//节点集合创建var rootNode = new Ext.tree.TreeNode({ id: 'root', text: '根节点', expanded: true }); //只展开根节点(只展开某节点)var node1 = new Ext.tree.TreeNode({ id: 'node1', text: 'Node1', leaf: true}); //为叶子节点var node2 = new Ext.tree.TreeNode({ id: 'node2', text: 'Node2' });var node3 = new Ext.tree.TreeNode({ id: 'node3', text: 'Node3', expanded: true });var arrNodes = [//节点集合new Ext.tree.TreeNode({ id: 'nodeOne', text: 'NodeOne' }),new Ext.tree.TreeNode({ id: 'nodeTwo', text: 'NodeTwo' }),new Ext.tree.TreeNode({ id: 'nodeThree', text: 'NodeThree' })];var arrayNodes = [new Ext.tree.TreeNode({ text: 'nodeOne' }), newExt.tree.TreeNode({ text: 'nodeTwo' })];node2.appendChild(arrayNodes); //将集合节点添加到对应的节点node3.appendChild(arrNodes);rootNode.appendChild(node1); //根节点添加对应的节点rootNode.appendChild(node2);rootNode.appendChild(node3);//也可以如下添加节点集合//rootNode.appendChild([node1, node2, node3]); //添加节点集合var treePanel = new Ext.tree.TreePanel({renderTo: Ext.getBody(), width: 150, root: rootNode,animate: true, //是否动画enableDD: true, //是否拖拽操作useArrows: true, //使用Vista-style箭头autoScroll: true, //是否自动滚动条containerScroll: true//向ScrollManager注册此容器});}2.简单TreePanel的使用//简单的树的练习function treeTest() {var rootNode = new Ext.tree.TreeNode({//创建根节点id: 'root', text: '树的根', nodeType: 'async'});rootNode.appendChild(new Ext.tree.TreeNode({ id: 'node1', text: 'Node1', leaf: true })); //是叶子节点,将不能添加子节点rootNode.appendChild(new Ext.tree.TreeNode({ id: 'node2', text: 'Node2', leaf: true }));var node3 = new Ext.tree.TreeNode({ id: 'node3', text: 'Node3' }); //创建节点3var arrNodes = [//节点集合new Ext.tree.TreeNode({ id: 'node30', text: 'Node30' }),new Ext.tree.TreeNode({ id: 'node31', text: 'Node31' }),new Ext.tree.TreeNode({ id: 'node32', text: 'Node32' })];node3.appendChild(arrNodes); //将节点集合添加到节点3中rootNode.appendChild(node3); //将节点3添加到根节点中var treePanel = new Ext.tree.TreePanel({//创建节点树对象renderTo: Ext.getBody(), root: rootNode, width: 200, animate: true, enableDD: true//animate动画效果,enableDD拖拽效果});//tree.getRootNode().expand(); //某个节点展开//node.expand(true);treePanel.expandAll(); //展开树下的所有节点//该节点下的所有子节点都触发//node3.eachChild(function () { alert('TT') });//某个节点(节点3)点击事件,鼠标位置//node3.on('click', function (node, e) { Ext.Msg.alert('信息提示', '你点击' + node.text + '的节点' + e.getXY()) });treePanel.on('click', function (node) {//所有节点都触发改事件if (node.hasChildNodes()) {//判断该节点是否含有子节点var msg = node.text + '有子节点:';var childNodes = node.childNodes; //取得该节点下的所有子节点for (var i = 0; i < childNodes.length; i++) {//遍历子节点集合msg += childNodes[i].text + '|'; //拼接节点集合文本信息}Ext.Msg.alert('信息提示', msg);} else {if (node.isLeaf()) {//判断该节点是否为叶子节点Ext.Msg.alert('信息提示', '你点击的是叶子节点:' + node.text);}}})}3.简单前台Ext Js对树的增删改//前台ExtJs操作对树的增删改操作function treeOperation() {var root = new Ext.tree.TreeNode({ text: '根节点' });var treePanel = new Ext.tree.TreePanel({width: 300, height: 600, renderTo: Ext.getBody(), root: root, id:'testTree',tbar: [{ text: '添加同级节点', handler: function (){ singleNodeInfo('addSibling', 'testTree'); } },{ text: '添加下级节点', handler: function (){ singleNodeInfo('addChild', 'testTree'); } },{ text: '修改节点', handler: function (){ singleNodeInfo('update', 'testTree'); } },{ text: '删除节点', handler: function (){ removeNode('testTree'); } }]});//treePanel.on('contextmenu', function (node, e) { var myMenu = createMenu(); node.select(); myMenu.showAt(e.getPoint()); });//对于节点内容的操作,也可以使用Ext.Msg.prompt来处理,如下://Ext.msg.prompt('请输入节点名称', '节点名称:', function (btn, text) { if (btn == 'ok') { alert(text); } });}function removeNode(treePanelID) {//删除节点,参数:树IDvar treePanel = Ext.getCmp(treePanelID);var selNode = treePanel.selModel.getSelectedNode();if (selNode == null) {Ext.Msg.alert('信息提示', '请选择你要删除的节点!');return;}if (!selNode.hasChildNodes()) {//是否包含子节点var removeNode = selNode.remove(); //其父节点移除自己Ext.Msg.alert('信息提示', '你移除了节点' + removeNode.text);}else {Ext.Msg.confirm('信息提示', '该节点为父节点,一并删除?', function (btn) { if (btn == 'yes') {selNode.removeAll(); //连同下面的子节点一起删除}});}}function AddAndUpdateNode(type, selNode, nodeName) {//添加\修改节点,参数:操作类型\选中节点\节点名字if (selNode != null) {switch (type) {case 'addChild': //添加子节点var addNode = new Ext.tree.TreeNode({ text: nodeName });selNode.appendChild(addNode);break;case 'addSibling': //添加同级节点var addNode = new Ext.tree.TreeNode({ text: nodeName });var parentNode = selNode.parentNode.appendChild(addNode);break;case 'update': //修改文本内容selNode.setText(nodeName);break;}selNode.expand(); //选中节点展开}}function singleNodeInfo(type, treeId) {//参数:操作类型,treePanel对象var treePanel = Ext.getCmp(treeId);var selNode = treePanel.selModel.getSelectedNode(); //获取选中的节点if (selNode == null) {Ext.Msg.alert('信息提示', '请选择一个节点');return;}var win = new Ext.Window({//弹出信息对话框title: '添加修改节点', width: 230, height: 100,bodyStyle: "padding-top:10px",items: [{ xtype: 'label', text: '节点名字:', width: 200 },{ xtype: 'textfield', id: 'txtNodeName' }],bbar: [{ text: '保存', handler: function () {var nodeName = Ext.getCmp('txtNodeName').getValue();AddAndUpdateNode(type, selNode, nodeName); //更新数据Ext.Msg.alert('信息提示', '保存成功!'); win.close();}}, '->',{ text: '取消', handler: function () { win.close(); } }]});if (type == "update") {Ext.getCmp('txtNodeName').setValue(selNode.text);}win.show(); //显示信息}//你也可以试试添加一个右键菜单对节点进行操作function createMenu() {var myMenu = new Ext.menu.Menu({ xtype: 'button', text: '添加节点', handler: function (tree) { Ext.Msg.alert('信息提示', '添加节点'); } },{ xtype: 'button', text: '下级节点', handler: function (){ Ext.Msg.alert('信息提示', '下级节点'); } },{ xtype: 'button', text: '修改节点', handler: function (){ Ext.Msg.alert('信息提示', '修改节点'); } },{ xtype: 'button', text: '删除节点', handler: function (){ Ext.Msg.alert('信息提示', '删除节点'); } });return myMenu;}4.简单树的异步加载(需要创建异步节点Ext.tree.AsyncTreeNode并使用Ext.tree.TreeLoader加载)(注意对于叶子节点的指定)function treeAsyncTest() {//树的异步加载,一次加载对应的数据var treePanel = new Ext.tree.TreePanel({el: 'divTree', //渲染divIDwidth: 150, height: 300, animate: true, enableDD: true, rootVisible: true, loader: new Ext.tree.TreeLoader({ url: 'TestTreeAjx.ashx', baseParams: { Option: 'GetAllData'} })});var rootNode = new Ext.tree.AsyncTreeNode({ text: '根节点' });treePanel.setRootNode(rootNode);treePanel.render(); //进行渲染rootNode.expand(true, true); //参数1:展开所有节点;参数2:启动动画效果//这样操作完你会发现所有的节点可能会无限的延展下去,//是因为数据引起的,在加载时,传出的数据指定最后一级为叶子节点就可以了}5.针对不同的节点异步加载不同的节点数据(注意对于叶子节点的指定)function treeNodeAsync() {//根据不同的节点值,获取不同的加载数据(可以是节点ID\节点文本等等)var rootNode = new Ext.tree.AsyncTreeNode({ text: 'rootNode' });var treePanel = new Ext.tree.TreePanel({el: 'divTree',width: 150, height: 300, animate: true, enableDD: true, rootVisible: true, listeners: {'beforeload': function (node) {//按这种形式传递的数据,不指定最后的叶子节点的话,会遍历每个节点,性能不好(如果需要,在对应节点下指定叶子节点)node.loader = new Ext.tree.TreeLoader({ url: 'TestTreeAjx.ashx', baseParams: { Option: 'GetNodeData', NodeText: node.text} })}}});treePanel.setRootNode(rootNode);//这里可以试试对于节点展开和非展开所有节点的数据加载情况//一次展开所有节点,会一次遍历完毕加载数据;不展开节点折叠起来,会在对应节点展开需加载时加载对应数据rootNode.expand(false, true);treePanel.render();}6.其Ajax请求页面TestTreeAjx.ashx代码(简单的模拟数据)namespace WebExtJS.WebTest{///<summary>/// TestTreeAjx 的摘要说明///</summary>public class TestTreeAjx : IHttpHandler{private static IDictionary<int, List<Node>> dic = null;public void ProcessRequest(HttpContext context){context.Response.ContentType = "text/plain";string strOption = context.Request["Option"] != null ?context.Request["Option"].ToString() : string.Empty;string nodeText = context.Request["NodeText"] != null ?context.Request["NodeText"].ToString() : string.Empty;string strMessage = string.Empty;dic = GetData();switch (strOption){case"GetAllData": strMessage = GetAllData(dic); break;case"GetNodeData": strMessage = GetNodeData(nodeText); break;default: break;}context.Response.Write(strMessage);context.Response.End();}///<summary>///获取全部的数据///</summary>///<returns></returns>private string GetAllData(){string data = "[{text:'Node1',leaf:true},"+"{text:'Node2',children:[{text:'Node20',leaf:true},{text:'Node21',leaf:true} ]},"+"{text:'Node3',children:[{text:'Node30',leaf:true},{text:'Node31',leaf:true},{text:'Node32',leaf:true}]}]";return data;}///<summary>///根据不同的节点文本获取对应的节点///</summary>///<param name="nodeText"></param>///<returns></returns>private string GetNodeData(string nodeText){string json = string.Empty;switch (nodeText){//指定叶子节点遍历非叶子节点(如果在其父节点指定为叶子节点,将不会加载对应的节点数据)case"rootNode": json ="[{text:'Node1',leaf:true},{text:'Node2'},{text:'Node3'}]"; break;case"Node2": json ="[{text:'Node20',leaf:true},{text:'Node21',leaf:true}]"; break;case"Node3": json ="[{text:'Node30',leaf:true},{text:'Node31',leaf:true},{text:'Node32',leaf:tr ue}]"; break;}//switch (nodeText)//{//不指定叶子节点遍历每一个节点// case "rootNode": json ="[{text:'Node1'},{text:'Node2'},{text:'Node3'}]"; break;// case "Node2": json = "[{text:'Node20'},{text:'Node21'}]"; break; // case "Node3": json ="[{text:'Node30'},{text:'Node31'},{text:'Node32'}]"; break;//}return json;}///<summary>///简单字典模拟数据///</summary>///<returns></returns>private IDictionary<int, List<Node>> GetData(){IDictionary<int, List<Node>> dic = new Dictionary<int, List<Node>>(); List<Node> nodeRoot = new List<Node>();List<Node> Node1 = new List<Node> { new Node(10, "Node10") };List<Node> Node2 = new List<Node> { new Node(20, "Node20"), new Node() { NodeID = 21, NodeName = "Node21" }, new Node() { NodeID = 22, NodeName = "Node22" } };List<Node> Node3 = new List<Node> { new Node(30, "Node30"), new Node(31, "Node31"), new Node(32, "Node32"), new Node(33, "Node33") };dic.Add(0, nodeRoot);//处理根节点dic.Add(1, Node1);dic.Add(2, Node2);dic.Add(3, Node3);return dic;}///<summary>///遍历拼接,获取全部数据///</summary>///<param name="dic"></param>///<returns></returns>private string GetAllData(IDictionary<int, List<Node>> dic){string json = string.Empty;json = "[";if (dic.Count > 0){for (int i = 0; i < dic.Count; i++){List<Node> tempNode;if (dic[i].Count == 0)//根节点判断{continue;}else{tempNode = dic[i];}if (tempNode.Count == 1)//只有一个叶子节点{json += "{text:'" + tempNode[0].NodeName + "'},";}else{json += "{text:'" + tempNode[0].NodeName + "',children:[";for (int j = 1; j < tempNode.Count; j++)//对其叶子节点遍历{json += "{text:'" + tempNode[j].NodeName +"',leaf:true},";}if (json.IndexOf(',') > 0){json = json.Substring(0, stIndexOf(','));}json += "]},";//闭合该节点}}}if (json.IndexOf(',') > 0){json = json.Substring(0, stIndexOf(','));json += "]";}return json;}public bool IsReusable{get{return false;}}}public class Node{public Node() { }public Node(int nodeID, string nodeName){this.NodeID = nodeID;this.NodeName = nodeName; }public int NodeID;public string NodeName;}}。
Extjs4.x Ext.tree.Panel 过滤Filter以及trigger field的使用(亲测代码可用)Extjs4.x中已经取消了组件Ext.Tree.TreeFilter功能,却掉了树形结构的过滤功能,要实现该功能只能自己写了.Tree节点筛选UI很简单,一个Tbar,一个trigger即可解决问题,剩下的是逻辑代码了。
1.tbar没啥好解析的2.trigger几个比较重要的属性triggerCls:文本框右侧的按钮样式,主要有4种x-form-clear-trigger // the X iconx-form-search-trigger // the magnifying glass iconx-form-trigger // the down arrow (default for combobox) iconx-form-date-trigger // the calendar icon (just in case) onTriggerClick:单击右侧按钮的事件emptyText:值为空时候显示的文字hideTrigger:是否显示触发按钮3.剩下最重要的一个是逻辑处理类完整的案例代码如下://先定义一个树状列表过滤类/*** Add basic filtering to Ext.tree.Panel. Add as a mixin:* mixins: {* treeFilter: 'WMS.view.TreeFilter'* }*/Ext.define('WMS.view.TreeFilter', {filterByText: function(text) {this.filterBy(text, 'text');},/*** Filter the tree on a string, hiding all nodes expect those which m atch and their parents.* @param The term to filter on.* @param The field to filter on (i.e. 'text').*/filterBy: function(text, by) {this.clearFilter();var view = this.getView(),me = this,nodesAndParents = [];// Find the nodes which match the search term, expand them.// Then add them and their parents to nodesAndParents.this.getRootNode().cascadeBy(function(tree, view){var currNode = this;if(currNode && currNode.data[by] && currNode.data[by].toString().toLower Case().indexOf(text.toLowerCase()) >-1) {me.expandPath(currNode.getPath());while(currNode.parentNode) {nodesAndParents.push(currNode.id);currNode = currNode.parentNode;}}}, null, [me, view]);// Hide all of the nodes which aren't in nodesAndParentsthis.getRootNode().cascadeBy(function(tree, view){var uiNode = view.getNodeByRecord(this);if(uiNode && !Ext.Array.contains(nodesAndParents, this.id)) { Ext.get(uiNode).setDisplayed('none');}}, null, [me, view]);},clearFilter: function() {var view = this.getView();this.getRootNode().cascadeBy(function(tree, view){var uiNode = view.getNodeByRecord(this);if(uiNode) {Ext.get(uiNode).setDisplayed('table-row');}}, null, [this, view]);}});//定义树状列表结构Ext.define("WMS.view.Tree", {extend: 'Ext.tree.Panel',alias: 'widget.wmsTree',id: 'wmsMenuTreePanel',title: "功能导航",margins: '0 0 0 3',width: 200,region: 'west',animate: true,store: 'VPTreeMenu',autoScroll: true,rootVisible: false,loadMsg: true,collapsible: true,//是否可以折叠split: true,tools: [{type: 'expand',handler: function () { Ext.getCmp("wmsMenuTreePanel").expandAll(); }}, {type: 'collapse',handler: function () { Ext.getCmp("wmsMenuTreePanel").collapseAll (); }}],//这里不要忘记,使用之前定义的过滤类来过滤树状列表mixins: {treeFilter: 'WMS.view.TreeFilter'},tbar: [{xtype: 'trigger',triggerCls: 'x-form-clear-trigger',onTriggerClick: function () {this.setValue('');Ext.getCmp("wmsMenuTreePanel").clearFilter();},width:'100%',emptyText:'快速检索功能',enableKeyEvents: true,listeners: {keyup: {fn: function (field, e) {if (Ext.EventObject.ESC == e.getKey()) {field.onTriggerClick();} else {Ext.getCmp("wmsMenuTreePanel").filterByText(this.g etRawValue());}}}}}]});如果你想对节点的中文做些处理,例如按照拼音首字母进行搜索,只需要变更如下这句代码即可currNode.data[by].toString().toLowerCase().indexOf(text.toLowerCase()) > -1更多扩展,可以自己修改类WMS.view.TreeFilter。
varorgPanel,appContextmenu,orgTreePanel= new Ext.ux.tree.TreeGrid({ 02 id:'orgTree',03 enableDD: true,04 region : 'center',05 enableSort:false,06 border:false,07 width:200,08 region:"west",09 margins:'0 4 0 0',10 title:'组织架构设置',11 useArrows: true,12 animate: true,13 columns:[{14 header:'组织',15 dataIndex: 'text',16 sortable:false,17 width: 18018 }],19 dataUrl : 'system/organization/resourceTree.json?type=1',20 root: new Ext.tree.AsyncTreeNode({21 id:'0',22 expanded:true23 }),24 tbar :[{25 iconCls : 'refreshItem',26 text : '刷新',27 handler : function() {28 orgTreePanel.loader.dataUrl = 'system/organization/resourceTree.json?type=1';29 orgTreePanel.root.reload();30 orgTreePanel.root.expand(true);31 }32 }, {33 text : '展开',34 tooltip : '展开',35 iconCls : 'addItem',36 handler : function(){37 orgTreePanel.root.expand(true);38 }39 }, {40 text : '收起',41 tooltip : '收起',42 iconCls : 'updateItem',43 handler : function(){44 orgTreePanel.collapseAll()45 }46 }],47 contextMenu: new Ext.menu.Menu({48 items: [{49 iconCls: 'add',50 text: '新建组织'51 }, {52 iconCls: 'edit',53 text: '编辑组织'54 }, {55 iconCls: 'delete',56 text: '删除组织'57 }],58 listeners: {59 itemclick: function(item){60 varnodeDataDel = item.parentMenu.contextNode.attributes;61 varparentNodeData = item.parentMenu.contextNode.parentNode;62 //varnodeData = orgPanel.getSelectionModel().getSelectedNode();63 switch (item.iconCls) {64 case 'add':65 createOrganizationFun(parentNodeDa ta);66 break;67case 'edit': 68 updateOrganizationFun(nodeDataDel,p arentNodeData);69 break;70 case 'delete':71 deleteOrganizationFun(nodeDataDel.i d,nodeDataDel.children.length==0?true:false);72break; 73 }74 item.parentMenu.hide();75 }76 }77 }),78 listeners: {79 afterrender: function(t) {80 treeMask=new Ext.LoadMask(t.getEl(), {msg:"数据加载中..."})81 orgTreePanel.root.expand(true);82 orgPanel = t;83 },84 contextmenu: function(node, e){85 appContextmenu = false;86 node.select();87 var tree = node.getOwnerTree();88 var c = tree.contextMenu;89 c.contextNode = node;90 c.showAt(e.getXY());91 }9293 }94 });二:接着要绑定treepanel 的点击事件:动态的根据树的节点去加载右边的内容:01 <span></span> //当点击组织机构树,动态加载数据jsp 页面内容 02 orgTreePanel.on('click', function(node) {03 if(node.id!='root'){04 Ext.getCmp('orgPer').getStore().baseParams={ 05 id:node.id06 };07 Ext.getCmp('orgPer').getStore().load();08 }09 var req=node.id10 window.frames['orgSet'].window.sendRequest(req); 11 });<span></span>这里右边的内容的展现,我用到了,frames 传参数去加载jsp 页面,这里把节点的参数通过frames 的方法传进jsp三:右边的带frame 的panel:01 //组织属性设置02 varorganizationSet = new Ext.Panel( {03 header : false,04 tbar : [{05 xtype : 'buttongroup',06 items : [{07 text : '新建组织',08 tooltip : '新建组织',09 iconCls : 'addItem',10 handler : function(){11 varnodeData,node = orgTreePanel.getSelectionModel().getSelectedNode();12 if(node){13nodeData=node.parentNode; 14 createOrganizationFun(nodeData,nodeData .id,nodeData.type);15 }else{16 Ext.Msg.alert('消息提示', '请左边选择一项!');17 }18 }19 }, {20 text : '添加部门',21 tooltip : '添加部门',22 iconCls : 'addItem',23 handler : function(){24 varnodeData,node = orgTreePanel.getSelectionModel().getSelectedNode();25 if(node){26 nodeData=node.attributes;27 addDepartmentFun(nodeData,nodeData.id,n odeData.type);28 }else{29 Ext.Msg.alert('消息提示', '请左边选择一项!');30 }31 }32 }]33 }],34 border:false,35 region:'north',36 height:220,37 monitorResize: true,38 autowidth:true,39 autoheight:true,40 frame:true,41 layoutConfig: {42 animate: true //动画效果启用43 },44 html: '<iframe id="orgSet" name="orgSet"src="organizationDetail.jsp" frameborder="0" width="100%" height="100%"></iframe>'45 });四:organizationDetail.jsp的内容:01 <%@page pageEncoding="UTF-8"%>02 <%@ taglib prefix="c" uri="/jsp/jstl/core" %>03 <%@ taglib prefix="fmt" uri="/jsp/jstl/fmt" %>04 <script type="text/javascript" src="js/jquery.js"></script>0506 <script type="text/javascript" language="javascript">07 function sendRequest(req) {0 8 $('#tabl').load('system/organization/content/'+req+'.htm') ;09 return;10 }11 </script>1213 <style type="text/css">14 .table-detail {15 margin: auto;16 width: 100%;17 }1819 .table-detail th {20 text-align: right;21 padding-right: 6px;22 color: #000;23 height: 32px;24 border: solid 1px #A8CFEB;25 font-weight: bold;26 text-align: right;27 font-size: 12px;28 font-weight: bold;29 padding-right: 5px;30 background-color: #edf6fc;31 padding-right: 5px;32 border: 1px solid #8dc2e3;33 }3435 .table-detail td {36 border: 1px solid #A8CFEB;37 font-size: 12px;38 padding-left: 6px;39 text-align: left;40 }41 </style>4243 <table width="98%" class="table-detail" cellpadding="0" cellspacing="1" id="tabl">44 <c:if test="${not empty organizationSets }"> 45 <tr>46 <th width="140">组织名称</th>47 <td>${}</td>48 </tr>49 <tr>50 <th>组织描述</th>51 <td>${organizationSets.desc}</td>52 </tr>53 <tr>54 <th>主要负责人</th>55 <td><%--${chargeUser }--%></td>56 </tr>57 <tr>58 <th>上级组织</th>59 <td>60 <c:if test="${not empty superior}"> 61 ${}62 </c:if>63 </td>64 </tr>65 <tr>66 <th>建立人</th>67 <td>${organizationSets.creatorName}</td>68 </tr>69 <tr>70 <th>建立日期</th>71 <td><fmt:formatDatevalue="${organizationSets.createtime}" pattern="yyyy-MM-ddHH:mm:ss"/></td>72 </tr>73 <tr>74 <th>修改人</th>75 <td>76 ${organizationSets.creatorName} 77 </td>78 </tr>79 <tr>80 <th>修改日期</th>81 <td>82 <fmt:formatDatevalue="${organizationSets.updatetime}" pattern="yyyy-MM-ddHH:mm:ss"/>83 </td>84 </tr>85 </c:if>86 </table >。
ExtJS 4 树先看个简单的效果图:Tree Panel是ExtJS中最多能的组件之一,它非常适合用于展示分层的数据。
Tree Panel和Grid Panel继承自相同的基类,所以所有从Grid Panel能获得到的特性、扩展、插件等带来的好处,在Tree Panel中也同样可以获得。
列、列宽调整、拖拽、渲染器、排序、过滤等特性,在两种组件中都是差不多的工作方式。
让我们开始创建一个简单的树组件Ext.create('Ext.tree.Panel', {renderTo: Ext.getBody(),title: 'Simple Tree',width: 150,height: 150,root: {text: 'Root',expanded: true,children: [{text: 'Child 1', leaf: true},{text: 'Child 2', leaf: true},{text: 'Child 3',expanded: true,children: [{text: 'Grandchild', leaf: true}]}]}});运行效果如图这个Tree Panel直接渲染在document.body上,我们定义了一个默认展开的根节点,根节点有三个子节点,前两个子节点是叶子节点,这意味着他们不能拥有自己的子节点了,第三个节点不是叶子节点,它有一个子节点。
每个节点的text属性用来设置节点上展示的文字。
Tree Panel内部使用Tree Store存储数据。
上面的例子中使用了root配置项作为使用store的捷径。
如果我们单独指定store,代码像这样:var store = Ext.create('Ext.data.TreeStore', {root: {text: 'Root',expanded: true,children: [{text: 'Child 1', leaf: true},{text: 'Child 2', leaf: true},...]}});Ext.create('Ext.tree.Panel', {title: 'Simple Tree',store: store,...});The Node Interface 节点接口上面的例子中我们在节点上设定了两三个不同的属性,但是节点到底是什么?前面提到,TreePanel绑定了一个TreeStore,Store在ExtJS 中的作用是管理Model实例的集合。
TreePanel的各项属性TreePanel的各项属性1、Ext.tree.TreePanel主要配置项:root:树的根节点。
rootVisible:是否显示根节点,默认为true。
autoScroll:当内容超过预设的高度时自动出现滚动条。
autoHeight: true 自动高度,默认为falsedraggable:是否允许拖曳。
enableDrag:true树的节点可以拖动Drag(效果上是),注意不是DraggableenableDD:设置树的节点是否可以拖动。
enableDrop:true//仅仅droplines:是否显示树线,默认为true。
loader:树节点的加载器,默认为Ext.tree.TreeLoader。
selModel:树的选择模式,默认为Ext.tree.DefaultSelectionModel。
pathSeparator:树节点路径的分隔符,默认为“/”。
singleExpand:是否一次只展开树中的一个节点,默认为true。
requestMethod:请求方法,可选值有POST、GET。
containerScroll:是否将树形面板注册到滚动管理器ScrollManager中。
useArrows:是否在树中使用Vista 样式箭头,默认为false。
主要方法:collapseAll():收缩所有树节点expandAll():展开所有树节点getRootNode():获取根节点getNodeById(String id):获取指定id的节点expand( [Boolean deep], [Boolean anim], [Function callback],[Object scope] )expandPath( String path, [String attr], [Function callback] )getChecked( [String attribute], [TreeNode startNode] )selectPath( String path, [String attr], [Function callback] )getSelectionModel():2、Ext.data.Node主要配置项:id:节点idleaf:当前节点是否为叶子节点主要属性:id:节点idattributes:节点属性的集合parentNode:当前节点的父节点childNodes:当前节点所有子节点组成的数组firstChild:当前节点的第一个直接子节点,如果没有则为null值lastChild:当前节点的最后一个直接子节点,如果没有则为null 值nextSibling:当前节点的下一个兄弟节点,如果没有则为null值previousSibling:当前节点的前一个兄弟节点,如果没有则为null值主要方法:appendChild( Node/Array node ):追加新的子节点bubble( Function fn, [Object scope], [Array args] ):从当前节点开始向上迭代调用指定函数,如果指定函数返回false则将终止迭代。