(更新版)ExtJS Tree利用json(直接传List TreeNode,不需要转化为JSONArray)在Struts 2实现Ajax动态加载树结点

这次能改进,我得写一个人--斌哥。他也是刚开始学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. 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 变量相同 -->
                    </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">

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值