这次能改进,我得感谢一个人--斌哥。他也是刚开始学JavaScript,加我QQ,我们是这样认识的。parentId 和 node 属性都是他创造的,也是动态异步加载的关键部分之一。这次的改进,我个人认为这应该是动态加载最简洁的做法。如有其它,还望高人指教,advance in thanks!
定义动态树的结点类 TreeNode.java
切记 : 该类的属性名称大部分 要和 Ext.tree.AsyncTreeNode或者Ext.tree.Node 的 Properties和Config Options一一对应,这样会自动导入到 Node 的属性中 ,这功能好迷人哦!但也可以传一些自己程序中要用的变量(如state,详见下文)。
每个属性的具体含义请参考ExtJS 的 API Documentation ,官方网址:http://www.extjs.com/
public class TreeNode {
private String id;// The node id
// 新增属性,这是实现动态异步加载的关键属性(09.10.31尝试后发现不用parentId也可以实现动态异步加载)
// private String parentId;// The parent node id
private int state;// 自己程序中用到的参数,具体怎么访问请参见下面的 treeNav.js
private String text;
// private List<TreeNode> children = new ArrayList<TreeNode>(); // 该属性不能实现异步加载
private String qtip;
private String icon;
private Boolean leaf;
private Boolean expanded;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
其它属性的 getter 和 setter 方法省略......
}
这个类没有实现序列化,但也可以序列化。两者的内在不同有待深究。
序列化代码如下所示,其它不变:
import java.io.Serializable;
public class TreeNode implements Serializable {
private static final long serialVersionUID = 7261712903068621559L;
ApplyFormAction .java
想实践 Struts 2 结合 Spring 实现项目的朋友,强烈推荐《Struts 2 In Action 》(我也是第一次读 英文版 ,很容易理解,电子书PDF网上有下载),内容很全。官方网址:http://struts.apache.org/
package cn.hdu.action.admin;
import java.util.ArrayList;
import java.util.List;
import cn.hdu.domain.admin.*;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import cn.hdu.service.admin.*;
@SuppressWarnings("serial")
public class ApplyFormAction extends ActionSupport{
// 当单击节点并触发Action时,都会将节点的id加载到参数中,而node一方面保存id,另一方面又是父节点id,服务于"
treeNode.setParentId(node ); "
private String node;
private List<TreeNode > treeNodes;
/**
* 只加载下一层节点信息
*/
public String bindAsTree()
{
results = applyFormService.findAll();
if(results != null) {
treeNodes = new ArrayList<AdminTreeNode>();
AdminTreeNode treeNode;
for(final ApplyForm af: results) {
treeNode = new AdminTreeNode();
treeNode.setId(af.getFormId().toString());
treeNode.setParentId(node );
treeNode.setText(af.getShortName());
treeNode.setState(af.getState());
treeNode.setQtip(af.getFormName());
treeNode.setIcon("images/icoImage/tree+.gif");
treeNode.setLeaf(false);
treeNodes.add(treeNode);
}
/*
首先,我 能做出这个要感谢先行者的付出才使我更向前一步!我这个的优势:不需要经过下面的转化,更不用将 nodesString 先输出到 JSP 页面上,然后 JavaScript 在读取它。这样就减省了这些不必要的转化时间,优势有没有自己衡量吧 ^-^
JSONArray jsonObject = JSONArray.fromObject(treeNodes);
try {
nodesString = jsonObject.toString();
} catch(Exception e) {
nodesString = "ss";
}
*/
}
return SUCCESS;
}
public String getNode() {
return node;
}
public void setNode(String node) {
this.node = node;
}
public List<TreeNode> getTreeNodes() {
return treeNodes;
}
public void setTreeNodes(List<TreeNode> treeNodes) {
this.treeNodes = treeNodes;
}
}
struts.xml
因为用到了 extends ="json-default" ,所以要导入 jsonplugin-0.30.jar
想了解更多关于 Struts 2 的 JSON 插件的朋友,不妨进入 http://cwiki.apache.org/S2PLUGINS/json-plugin.html
<param name="root ">中的 root 设置是实现该功能成功的关键点之一。
<action name="bindAsTree" class="cn.hdu.action.admin.ApplyFormAction" method="bindAsTree">
<result type="json">
<param name="root "> <!-- 这里的name属性值一定要为 root,
Use the "root" attribute(OGNL expression) to specify the root object to be serialized(刚开始没成功可能是
TreeNode
序列化
引起的!若这里不设置root,则将
TreeNode
类先序列化
,应该也可以成功,没试过。) .
The parameter "root" should point to the getter property of the action object which contains the object to convert to JSON string data.
-->
treeNodes <!-- 一定要和
ApplyFormAction .java 中的红色标记
treeNodes 变量相同。不一定要这样,只要有getTreeNodes,变量名可以是其它,可以参考Spring的Getter和Setter实现原理。
-->
</param>
</result>
</
action
>
</
package
>
表现层
treeNav.js
利用 ExtJS 作为开发工具的朋友,一定要充分利用其官方网站:http://www.extjs.com/ 。上面不但提供了各控件的不同功能实现的实例(可视化)和源代码(Firefox浏览器的Firebug调试插件可以得到所有的源码,好好利用吧),但可惜都不是动态的。还有就是非常详细的 API Documentation,这是开发人员的首选参考资料, 可以在其官方网址:http://www.extjs.com/ 下载到。
Ext.onReady(function(){
Ext.BLANK_IMAGE_URL = 'ext-2.0.2/resources/images/default/s.gif';
Ext.QuickTips.init();
// set the root
var root = new Ext.tree.AsyncTreeNode( {
text : '根结点',
draggable : false,
id : '-100'
});
var tree = new Ext.tree.TreePanel( {
rootVisible: false,
// height: 500,
margins: '5 5 4 5',
autoScroll: true,
// el: 'tree',
renderTo: 'tree ', // Using this config, a call to render() is not required (在html中存在一个 id 为 tree 的结点)
animate: true,
enableDD: false,
title: '计划体系分类',
root: root, // You must define the root variable before when you set the root config
loader: new Ext.tree.TreeLoader({
dataUrl : 'admin/bindAsTree.action'
}),
listeners: {
beforeclick: function(node, e) {
if(node.id[0] != 'r') {
if(node.attributes.state == 2) { // You can use this property to access any custom attributes you supplied (你可以通过
attributes
这个
属性获得任何你提供的属性值 )
jumpToApplyFrame(parseInt(node.id));
} else if(node.attributes.state == 1) {
Ext.Msg.alert('友情提示','此类项目申报尚在建设中。。。请关注!',function(){});
} else if(node.attributes.state == 3) {
Ext.Msg.alert('友情提示','此类项目申报已暂停使用!',function(){});
}
}
},
click: function(node, e) {
if(node.isLeaf()) {
} else {
// This node is expanded when it is not leaf node
node.toggle();
}
}
}
});
// tree.setRootNode(root);
// tree.render('tree');
root.expand();
});
function jumpToApplyFrame(formId)
{
var formIdType = document.getElementById('formIdType');
var paraForm = document.getElementById('id_treePara');
formIdType.value = formId;
paraForm.submit();
}
最后,只要在相应的 html 文件中有如下代码即可:
<div id="tree"></div>
大功告成!
小结:
在STRUTS中使用EXTJS中的TREE实现异步加载树节点 http://www.blogjava.net/aoneany/articles/193537.html 这篇的 struts.xml 的 params="root "最为关键,那是最容易显示不了效果的地方,参见上文的 xml 文件即可。这是个牛人啊,崇拜!
还有一点教训 ,希望对后来者有用:
(1) 我在设置 TreeNode 的 id 属性时,将一些结点的 id 属性设置相同。这导致只有其中一个结点可用,其它的被自动屏蔽为不可用 。
(2)关于s.gif 文件的问题
该问题会在系统不连互联网的情况下暴露。
因为ExtJS在生成Tree时,默认情况下,总是访问http://extjs.com/s.gif下载这个s.gif图片文件。
在不连网的情况下,树节点的导航图片显示不出,通过右键属性可知,是http://extjs.com/s.gif。
通过搜索,发现该s.gif是在ext-base.js这个文件中定义的:
BLANK_IMAGE_URL:"http:/"+"/extjs.com/s.gif"
并且ExtJS中的示例程序是带有这个s.gif图片文件的。
根据具体应用情况,把ext-base.js修改成为:
BLANK_IMAGE_URL:"../images/default/s.gif"
或在mytree.js 文件开头加入如下语句:Ext.BLANK_IMAGE_URL="../images/default/s.gif"; 建议这么做。
Ext.BLANK_IMAGE_URL needs to be better for the end developer
Ext.BLANK_IMAGE_URL=Ext.isIE6||Ext.isIE7||Ext.isAir? "resources/images/default/s.gif" : "data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
2009年9月2日,本人碰到的问题 。如果对 s.gif 的引用路径不正确(即不能加载该图片),会导致树的树形导航线不能显示,忘朋友们注意。
(3) 调试的时候,JS报错:未结束的字符串常量。
这个问题是因为JS调用时没有指定字符集,造成JS里的汉字出现乱码引起的。
调用JS时,可以指定使用字符集。
如:<script type="text/javascript" defer=true src="xxx.js" charset="utf-8">
版权声明:
如果大家要转载本文,我非常荣幸。但请参加转载网址,谢谢!