2012/11/20javascript
发现项目中用到一个TreeCheckNodeUI插件,直接添加checked属性并不能实现级联选择,不少关于选择的部分还要本身实现,这个插件帮助完成了这些事情。php
貌似是插件出处?css
相关:EXT2.0 checkbox树的扩展(级联)_测试及解决方案html
虽然不错,仍是存在Bug,并且没有半选状态,而后发现了还有三态的版本java
这个不错,在上面稍微作了点修改就用上了,可是代码没有全理解... 能够像使用上面那个插件那样使用,不用把TreeLoader
改为他定义的TreeCheckLoader
数组
其它:app
虽然走了点弯路,可是理解了DwrTreeLoader是怎么使用的。
========== 华丽的分割线 ==========
需求:在项目中使用了DwrTreeLoader来做为ExtJS的TreeLoader,有的树控件须要显示CheckBox,而有的不须要显示,经过传入参数来控制是否显示CheckBox
参考:ExtJs结合Dwr的tree,没有介绍如何传参数,做为入门Demo
要使TreeNode带复选框,只要加上checked
属性便可,可参考Ext结合Dwr带复选框的树,基本的代码和上面那篇文章没啥区别
网上有一篇写ExtJS中DWRTreeLoader的两个版本的差异, 其实没啥区别,只是DWRTreeLoader.js源代码中一个属性的名称改了一下
由于对上面Demo的改动比较大,并且网上也没有解释得比较清楚的文章,故写这篇文章做为记录
Demo结构:
首先,配置Extjs,按目录结构里面的拷贝几个文件就好了,这里用的是3.x的版本(由于目前作的项目用的这个版本,测试了下4.x的版本没有成功,不知道问题在哪)
接着,要配置Dwr,直接把以前写的DwrDemo的几个文件拷贝过来就搞定了,这里不重复说明
dwr.xml
<!-- lang: xml --> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd"> <dwr> <allow> <create creator="new" javascript="TreeService"> <param name="class" value="zoey.extjs.dwr.tree.TreeService" /> </create> <convert converter="bean" match="zoey.extjs.dwr.tree.Node" /> </allow> </dwr>
Node.java修改成使用Map<String, Object>
来保存结点属性,能够更灵活
<!-- lang: java --> package zoey.extjs.dwr.tree; import java.util.HashMap; import java.util.Map; public class Node { private Map<String, Object> nodeMap; public Node(int id, String text, boolean leaf, boolean checkBox) { nodeMap = new HashMap<String, Object>(); nodeMap.put("id", id); nodeMap.put("text", text); nodeMap.put("leaf", leaf); // 经过传入的参数checkBox是否为true,来控制是否显示复选框 if (checkBox) { nodeMap.put("checked", false); } } public Map<String, Object> getNodeMap() { return nodeMap; } public void setNodeMap(Map<String, Object> nodeMap) { this.nodeMap = nodeMap; } }
TreeService.java
<!-- lang: java --> package zoey.extjs.dwr.tree; import java.util.ArrayList; import java.util.List; import java.util.Map; public class TreeService { public List<Map<String, Object>> getAllChildren(String parentId, boolean checkBox) { List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); if (parentId.equals("root")) { list.add(new Node(1, "子节点1", false, checkBox).getNodeMap()); list.add(new Node(2, "子节点2", false, checkBox).getNodeMap()); list.add(new Node(3, "子节点3", false, checkBox).getNodeMap()); list.add(new Node(4, "子节点4", false, checkBox).getNodeMap()); list.add(new Node(5, "子节点5", false, checkBox).getNodeMap()); list.add(new Node(6, "子节点6", false, checkBox).getNodeMap()); } else if (parentId.equals("2")) { list.add(new Node(7, "孙子节点7", true, checkBox).getNodeMap()); list.add(new Node(8, "孙子节点8", true, checkBox).getNodeMap()); list.add(new Node(9, "孙子节点9", true, checkBox).getNodeMap()); } else if (parentId.equals("4")) { list.add(new Node(11, "孙子节点11", true, checkBox).getNodeMap()); list.add(new Node(12, "孙子节点12", true, checkBox).getNodeMap()); list.add(new Node(13, "孙子节点13", true, checkBox).getNodeMap()); } else if (parentId.equals("6")) { list.add(new Node(21, "孙子节点21", true, checkBox).getNodeMap()); list.add(new Node(22, "孙子节点22", true, checkBox).getNodeMap()); list.add(new Node(23, "孙子节点23", true, checkBox).getNodeMap()); } return list; } }
tree.js
<!-- lang: js --> Ext.onReady(function() { var root = new Ext.tree.AsyncTreeNode({ id: "root", leaf: false, text: "树的根", checked: false // ===== 控制根结点显示CheckBox ===== }); var treeloader = new Ext.ux.DWRTreeLoader({ // 构造器调用模式 // ===== 属性名为dwrCall,由于DWRTreeLoader.js中调用了这个属性, // (搜"this.dwrCall"可搜到,旧的名称为dwrMethod或dataURL, // 关键看DWRTreeLoader中怎么命名的) ===== dwrCall: TreeService.getAllChildren, // ===== 传入参数,DWRTreeLoader中可以使用this.params进行调用,名字可有可无,也能够不写成这种形式 // 关键是知道在DWRTreeLoader中可使用this调用这里的属性 ===== params: { checkBox: true } }); var viewTree = new Ext.tree.TreePanel({ id: "vtree", renderTo: "tree", root: root, loader: treeloader, width: 200, height: 300, title: "动态遍历树", useArrows: true, //是否使用箭头样式 autoScroll: true, //滚动条 animate: true, //展开,收缩动画 rootVisible: true, //根节点是否可见 // enableDD: true, //是否能够拖放节点 tools: [{ id: 'refresh', handler: function () { var tree = Ext.getCmp('vtree'); tree.body.mask("数据加载中..", "x-mask-loading"); tree.root.reload(); tree.root.expand(true, false, function() { tree.body.unmask(); }); } }], region: "west", collapseMode: "mini", collapsible: true, //面板是可收缩的,并自动渲染一个展开/收缩的轮换按钮在头部工具条 split: true, border: false }); });
DWRTreeLoader.js
可在这里找到最原始的代码:DwrTreeLoader source
这里稍微作了修改(只给出修改的部分):
<!-- lang: js --> /** * Override this to add custom request parameters. Default adds the node id as first and only parameter */ getParams : function (node) { var callParams = []; callParams.push(node.id); for (var key in this.params) { callParams.push(this.params[key]); } return callParams; },
上面的this.params
就是new Ext.ux.DWRTreeLoader({})
中传入的属性
在requestData
函数中有callParams
数组,采用了apply调用模式,this.dwrCall.apply(this, callParams);
,callParams数组做为参数传入TreeService.getAllChildren
函数,须要注意传入参数的顺序。
index.jsp
<!-- lang: html --> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path; %> <!DOCTYPE html> <html> <head> <base href="<%=basePath%>"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Hello ExtJS DWR Tree</title> <link rel="stylesheet" type="text/css" href="<%=basePath%>/extjs/resources/css/ext-all.css" /> <script type="text/javascript" src="<%=basePath%>/extjs/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="<%=basePath%>/extjs/ext-all.js"></script> <script type="text/javascript" src="<%=basePath%>/js/tree.js"></script> <script type='text/javascript' src='<%=basePath%>/js/DWRTreeLoader.js'></script> <script type='text/javascript' src='<%=basePath%>/dwr/engine.js'></script> <script type='text/javascript' src='<%=basePath%>/dwr/interface/TreeService.js'></script> <script type='text/javascript' src='<%=basePath%>/dwr/util.js'></script> </head> <body><div id="tree"></div></body> </html>
这里就能够经过设置params: { checkBox: true }
的checkBox
值为true
或false
来控制是否显示复选框了
也能够传入其它的参数,在后台作更多的扩展
注:对代码的解释部分,水平有限按本身的想法说明,发现不对的会即时改正。