extjs3.3.0+struts2.1.8.1+spring3.0.4+hibernate3.5.4+oracle10g实现动态树
利用extjs在web端显示一棵树,而数据库存放的也是一棵树,点击一个节点,然后发起一个请求去查询其子节点。我采用了一个区域表,一个区域有一个或者多个子区域而一个区域仅有一个父区域。数据库表的生成采用hibernate,初始化数据
通过解析xml利用hibernate插入。环境如下:
动态树js文件:dymictree.js如下:
Ext.onReady(function() {
/**
* 初始化提示系统
*
* @author centre
*/
var m = Ext.QuickTips.init();
/**
* 创建一个异步根节点
*
* @author centre
*/
var root = new Ext.tree.AsyncTreeNode({
id : "0",
text : "管理菜单",
expanded : true
});
/**
* 创建一个树加载器
*
* @author centre
*/
var myLoader = new Ext.tree.TreeLoader({
url : "crudTree!loadTree",
/**
* 返回的数据形式如下:
*/
baseParams : {
treeNodeId : "0"
},
listeners : {
"loadexception" : function(loader, node, response) {
// 加载服务器数据,直到成功
node.loaded = false;
node.reload.defer(10, node);
}
}
});
/**
* 加上beforeload事件监听,用于在这个事件前确定向后台java代码发送参数
*
* @author centre
*/
myLoader.on("beforeload", function(loader, node) {
loader.baseParams.treeNodeId = node.id;
});
/**
* 创建一个treepanel容器,用于放置这颗树
*
* @author centre
*/
var secondTree = new Ext.tree.TreePanel({
el : "container1",
animate : true,
title : "Extjs动态树(动态加载节点,动态增删改)",
collapsible : true,
enableDD : true,
enableDrag : true,
rootVisible : true,
autoScroll : true,
height : 800,
width : 200,
lines : true,
loader : myLoader,
root : root,
listeners : {
// 监听右键点击事件
"contextmenu" : function(node, e) {
// alert(node.isLeaf());
if (node.isLeaf()) {
// 如果是叶子节点,弹出右键菜单
var nodemenu = new Ext.menu.Menu({
// 包括3个选项,添加小类别,编辑小类别,删除小类别
items : [{
text : "添加小类别",
iconCls : 'leaf',// 右键名称前的小图片
handler : function() {
Ext.MessageBox.prompt("请输入新项名称", "", function(
e, text) {
if (e == "ok") {
Ext.Ajax.request({
url : 'CrudTree!addNewNode',
params : {
newNodeId : node.parentNode.id
.substring(2),
nodeName : text
},
success : function(request) {
secondTree.root
.reload();// 数的重新加载
secondTree.root.expand(
true, false);
},
failure : function() {
alert("添加失败");
}
});
} else {
alert("您取消了插入叶子节点!");
}
})
}
}, {
text : "编辑小类别",
iconCls : 'leaf',
handler : function() {
Ext.MessageBox.prompt("请输入此项新名称", "", function(
e, text) {
if (e == "ok") {
Ext.Ajax.request({
url : 'CrudTree!updateNode',// 传递需要的值,服务器会执行修改
params : {
editNodeId : node.parentNode.id
.substring(2),
editNodeName : text
},
success : function(request) {
secondTree.root
.reload();
secondTree.root.expand(
true, false);
},
failure : function() {
alert("修改节点失败");
}
});
} else {
alert("您取消了编辑节点!");
}
})
}
}, {
text : "删除小类别",
iconCls : 'leaf',
handler : function(e, text) {
Ext.Ajax.request({
url : 'CrudTree!deleteNode',// 根据id删除节点
params : {
deleteNodeId : node.parentNode.id
.substring(2)
},
success : function(request) {
secondTree.root.reload();
secondTree.root.expand(true,
false);
},
failure : function() {
alert("删除操作失败,请重试.");
}
});
}
}]
});
nodemenu.showAt(e.getPoint());// menu的showAt,不要忘记
} else if (!node.isLeaf() && node.parentNode != null) {
// 当当前节点不是根节点也不子节点时,
// 包括3个类别:添加大类别,编辑大类别,删除大类别
var nodemenu = new Ext.menu.Menu({
items : [{
text : "添加大类别",
iconCls : 'folder',
handler : function(e, text) {
// 1. 传递2个参数,id和name
// 2.通过ajax操作数据库
// 3.刷新树
alert("添加节点name:" + text)
}
}, {
text : "编辑大类别",
iconCls : 'folder',
handler : function(e, text) {
// 1.传递2个参数,要修改的节点的id和新的名字
// 2.通过ajax传递到后台操作数据库
// 3.刷新树
alert("编辑节点的name:" + text)
}
}, {
text : "删除大类别",
iconCls : 'folder',
handler : function(e, text) {
// 1.传递2个参数,要修改的节点的id和新的名字
// 2.通过ajax传递到后台操作数据库
// 3. 刷新树
alert("执行事件代码")
}
}]
});
// 显示在点击右键的地方
nodemenu.showAt(e.getPoint());
}
}
}
});
secondTree.render();
});
这个树要访问的action,就是在目录下的action。代码如下:
package com.xxx.javatask.action;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.hikvision.javatask.service.AreaService;
import com.opensymphony.xwork2.ActionSupport;
/**
* @ProjectName: 动态树实现,实现动态增加节点,删除节点和编辑节点
* @Copyright:
* @address:
* @date: 2011-8-16 20:01
* @Description:
* @author centre
*/
public class CrudTree extends ActionSupport {
private static final long serialVersionUID = 1L;
// log4j的日志实例
private static Logger logger = LoggerFactory
.getLogger("com.hikvision.javatask.action.CrudTree");
private HttpServletRequest request;
private HttpServletResponse response;
private AreaService areaService;
/**
* 通过request 接收参数,查找数据库,向web端返回一个json对象数组的字符串
*
* @author centre
* @return 该方法没有返回值
*/
public void loadTree() {
request = ServletActionContext.getRequest();
response = ServletActionContext.getResponse();
String id = request.getParameter("treeNodeId");
String jsonRet =areaService.areaTreeNode(id);
ajaxReturnJsonData(jsonRet, request, response);
}
/**
* 向web端写回一个字符串,本处通常写回的是json对象或者json对象数组的字符串
*
* @author centre 2011-8-16 20:06
* @param ret
* 需要向web返回的字符串
* @param request
* HttpServletRequest
* @param response
* HttpServletResponse
*/
private void ajaxReturnJsonData(String ret, HttpServletRequest request,
HttpServletResponse response) {
try {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.getWriter().write(ret);
logger.debug("数据返回成功");
} catch (IOException e) {
logger.error("数据返回错误。请查看业务逻辑。");
e.printStackTrace();
}
}
public AreaService getAreaService() {
return areaService;
}
public void setAreaService(AreaService areaService) {
this.areaService = areaService;
}
}