2012/11/20
发现项目中用到一个TreeCheckNodeUI插件,直接添加checked属性并不能实现级联选择,很多关于选择的部分还要自己实现,这个插件帮助完成了这些事情。
相关:EXT2.0 checkbox树的扩展(级联)_测试及解决方案
虽然不错,还是存在Bug,而且没有半选状态,然后发现了还有三态的版本
这个不错,在上面稍微做了点修改就用上了,但是代码没有全理解... 可以像使用上面那个插件那样使用,不用把TreeLoader
改成他定义的TreeCheckLoader
其它:
虽然走了点弯路,但是理解了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
来控制是否显示复选框了
也可以传入其它的参数,在后台做更多的扩展
注:对代码的解释部分,水平有限按自己的想法说明,发现不对的会即时改正。