ExtJS4+Servlet/Struts2+JSON+accordion布局动态Ext.tree.Panel菜单
http://blog.csdn.net/leecho571/article/details/7051825
先贴个图给大家,实现的是一个Accordion布局的动态菜单,俗称手拉琴布局,切入正题:
首先构造出一个窗口(Ext.window.Window),布局选择Accordion,代码:
[javascript] view plain copy print ?
- var win = Ext.create("Ext.window.Window", {
- title : "Accordion布局动态菜单",
- width : 300,
- height : 500,
- iconCls : "icon-accordion",
- autoScroll : false,
- layout : 'accordion',
- layoutConfig : {
- animate : true
- }
- });
- win.show();
var win = Ext.create("Ext.window.Window", { title : "Accordion布局动态菜单", width : 300, height : 500, iconCls : "icon-accordion", autoScroll : false, layout : 'accordion', //设置布局 layoutConfig : { animate : true //动态切换树空间 } }); win.show();
然后向后台发送AJAX请求,获取窗口的面板列表:
[javascript] view plain copy print ?
- ajax({
- url : "/Accordion/accordion",
- params : {
- action : "list"
- },
- callback : addTree
- });
ajax({ url : "/Accordion/accordion",//获取面板的地址 params : { action : "list" }, callback : addTree });
这里对Ext.Ajax.request方法做了一个简易的封装:
[javascript] view plain copy print ?
- var ajax = function(config) {
- Ext.Ajax.request({
- url : config.url,
- params : config.params,
- method : 'post',
- callback : function(options, success, response) {
- config.callback(Ext.JSON.decode(response.responseText));
-
- }
- });
- return false;
- };
var ajax = function(config) { //封装、简化AJAX Ext.Ajax.request({ url : config.url, //请求地址 params : config.params, //请求参数 method : 'post', //方法 callback : function(options, success, response) { config.callback(Ext.JSON.decode(response.responseText)); //调用回调函数 } }); return false; };
在SERVLET代码里面,准备树面板的数据,在doPost方法中根据action判断是获取面板列表还是树节点,然后将数据发送到页面,renderText方法不是很关键,大家可以去下载源码看看,这里就不写出来:
[java] view plain copy print ?
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- String action = request.getParameter("action");
- initHeader(response);
- if(action.equals("list")){
- renderText(this.getTreePanelList(), response);
- }else if(action.equals("node")){
- renderText(this.getTreeNodeList(request.getParameter("id")), response);
- }
- }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String action = request.getParameter("action"); initHeader(response); if(action.equals("list")){//获取属面板列表 renderText(this.getTreePanelList(), response); }else if(action.equals("node")){ renderText(this.getTreeNodeList(request.getParameter("id")), response); } } 这里获取的树面板列表,调用方法:
[java] view plain copy print ?
- public String getTreePanelList(){
- JSONArray array = new JSONArray();
- for (int i = 0; i < 5; i++) {
- JSONObject json = new JSONObject();
- json.element("id", i+1);
- json.element("iconCls", "icon-panel");
- json.element("title", "Accordion菜单"+(i+1));
- array.add(json);
- }
- return array.toString();
- }
public String getTreePanelList(){ JSONArray array = new JSONArray(); for (int i = 0; i < 5; i++) { //生成5个属面板 JSONObject json = new JSONObject(); json.element("id", i+1); json.element("iconCls", "icon-panel"); json.element("title", "Accordion菜单"+(i+1)); array.add(json); } return array.toString(); } 通过Google Chrome的开发工具来查看获取的树面板列表数据:
在获取属面板列表成功之后,执行addTree回调函数,根据获取的数据生成树面板(Ext.tree.Panel)树面板添加进窗口中,在生成树面板之前得先给树面板的树注册一个数据源以及为数据源指定数据模型,数据模型的作用主要是可以将自己想要的业务数据即和树展示无关的数据传递到页面,方便使用:
[javascript] view plain copy print ?
- function addTree(data){
- for ( var i = 0; i < data.length; i++) {
- win.add(Ext.create("Ext.tree.Panel", {
- title : data[i].title,
- iconCls : data[i].iconCls,
- autoScroll : true,
- rootVisible : false,
- viewConfig : {
- loadingText : "正在加载..."
- },
- store : createStore(data[i].id)
- }));
- win.doLayout();
- }
- }
- var model = Ext.define("TreeModel", {
- extend : "Ext.data.Model",
- fields : [ {name : "id",type : "string"},
- {name : "text",type : "string"},
- {name : "iconCls",type : "string"},
- {name : "leaf",type : "boolean"}
- ]
- });
- var createStore = function(id){
- var me = this;
- return Ext.create("Ext.data.TreeStore",{
- defaultRootId : id,
- model : model,
- proxy : {
- type : "ajax",
- url : "/Accordion/accordion?action=node"
- },
- clearOnLoad : true,
- nodeParam : "id"
- });
- };
function addTree(data){ for ( var i = 0; i < data.length; i++) { win.add(Ext.create("Ext.tree.Panel", { title : data[i].title, iconCls : data[i].iconCls, autoScroll : true, rootVisible : false, viewConfig : { loadingText : "正在加载..." }, store : createStore(data[i].id) })); win.doLayout(); } } var model = Ext.define("TreeModel", { //定义树节点数据模型 extend : "Ext.data.Model", fields : [ {name : "id",type : "string"}, {name : "text",type : "string"}, {name : "iconCls",type : "string"}, {name : "leaf",type : "boolean"} ] }); var createStore = function(id){ //创建树面板数据源 var me = this; return Ext.create("Ext.data.TreeStore",{ defaultRootId : id, //默认的根节点id model : model, proxy : { type : "ajax", //获取方式 url : "/Accordion/accordion?action=node" //获取树节点的地址 }, clearOnLoad : true, nodeParam : "id"//设置传递给后台的参数名,值是树节点的id属性 }); };
最后就是实现如果生成树节点的的数据:
[java] view plain copy print ?
- public String getTreeNodeList(String id){
- JSONArray array = new JSONArray();
- for (int j = 0; j < 5; j++) {
- JSONObject json = new JSONObject();
- json.element("id", id + "-" +(j+1));
- json.element("text", "树节点-"+ id + "-" +(j+1));
- if((j+1) % 2 == 0 && id.length() <= 3){
- json.element("leaf", false);
- }else{
- json.element("leaf", true);
- }
- array.add(json);
- }
- return array.toString();
- }
public String getTreeNodeList(String id){ //获取树节点的数据 JSONArray array = new JSONArray(); for (int j = 0; j < 5; j++) { JSONObject json = new JSONObject(); json.element("id", id + "-" +(j+1)); json.element("text", "树节点-"+ id + "-" +(j+1)); if((j+1) % 2 == 0 && id.length() <= 3){ //判断顺序为偶数的节点,及层数不超过三层的节点可以加载子节点 json.element("leaf", false); //通过leaf属性来控制树节点是否是叶子节点(没有子节点的节点),能否加载数据 }else{ json.element("leaf", true); } array.add(json); } return array.toString(); } 然而通过这些代码实现后会发现一个属面板展示上的BUG,树面板里面的树空间的宽度不正确:
这是一个Ext4的BUG,不过不要紧,BUG总是可以会修复的,将addTree的代码改造一下,给树面板注册一个afterLayout的监听器,实例当中的代码是改造后的,只是跟大家说明下这段代码的用途:
[javascript] view plain copy print ?
- function addTree(data){
- for ( var i = 0; i < data.length; i++) {
- win.add(Ext.create("Ext.tree.Panel", {
- title : data[i].title,
- iconCls : data[i].iconCls,
- autoScroll : true,
- rootVisible : false,
- viewConfig : {
- loadingText : "正在加载..."
- },
- store : createStore(data[i].id),
- listeners : {
- afterlayout : function(){
- if(this.getView().el){
- var el = this.getView().el;
- var table = el.down("table.x-grid-table");
- if(table){
- table.setWidth(el.getWidth());
- }
- }
- }
- }
- }));
- win.doLayout();
-
- }
- }
function addTree(data){ for ( var i = 0; i < data.length; i++) { win.add(Ext.create("Ext.tree.Panel", { title : data[i].title, iconCls : data[i].iconCls, autoScroll : true, rootVisible : false, viewConfig : { loadingText : "正在加载..." }, store : createStore(data[i].id), listeners : { afterlayout : function(){ if(this.getView().el){ var el = this.getView().el; var table = el.down("table.x-grid-table"); if(table){ table.setWidth(el.getWidth()); } } } } })); win.doLayout(); } }
最后一个话题,在STRUTS中如何实现,很简单:也是准备数据,然后将数据发送到页面就可以!
这样,一个Accordion布局整合SERVLET/STRUTS2+JSON+动态Ext.tree.Panel菜单就OK了!
下面是展示两张将这个模块应用到系统中的效果: