这是一个ExtJS实现的树展示,后台使用的EJS构架,因此向大家推荐,内容转自willamRaym的blog。
最近在学习ExtJS,发现其服务器端是php,这一点对我们搞java的有点不厚道啊。昨天学习了ExtJS的树,并做了一棵异步更新的树出来,后台的业务逻辑及持久层使用JPA+Spring2.5实现,发下面把步骤贴出来与大家分享。
首先准备树的域模型,下面是一地区的域模型对象, Region.java 的代码如下:
@Entity
![](https://i-blog.csdnimg.cn/blog_migrate/1fa987a29c6482f53d401256f96355eb.gif)
public
class
Region
{
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
@Field(name = " 名称 " ,validator = @Validator(name = " string " ,value = " min:2;max:50 " ,required = true ))
@Column(length = 100 )
private String name;
@Field(name = " 编码 " ,validator = @Validator(name = " string " ,value = " min:2;max:16 " ,required = true ))
@Column(length = 100 )
private String code;
@POLoad(name = " parentId " )
@ManyToOne
private Region parent;
@OneToMany(mappedBy = " parent " ,fetch = javax.persistence.FetchType.EAGER)
private List < Region > children = new java.util.ArrayList < Region > ();
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
public Long getId()
{
return id;
}
public void setId(Long id)
{
this .id = id;
}
Region域模型有parent,也有children,这个完全是一个树的结构,如果把树根砍了话就变成森林了,呵呵这一点跟现实不一样。其它都是setter及getter方法,这里就不多说了。
然后我们就要做针对这个地区信息的添删除改查了。呵呵,添删改查我最拿手了,特别是基于EJS(EasyJWeb+JPA+Spring2)构架的添删改查,一个命令搞定了。这里就不多说了,大家可以直接看我前段时间做的视频演示(http://www.easyjf.com/blog/html/20080102/1015814.html)。当然这个示例由于是分级别的,所以生成的添删改查还要改一改,才支持上下级管理功能。
下面进入我们重点部分,如何在页面中得到一棵表示地区的树。
首先准备一个tree.html,内容如下:
<
html
>
<
head
>
<
meta
http-equiv
="Content-Type"
content
="text/html; charset=UTF-8"
/>
<
title
>
ExtJS-树示例
</
title
>
<
link
rel
="stylesheet"
type
="text/css"
href
="/plugins/extjs/ext-2.0/resources/css/ext-all.css"
/>
<
script
type
="text/javascript"
src
="plugins/extjs/ext-2.0/adapter/ext/ext-base.js"
></
script
>
<
script
type
="text/javascript"
src
="plugins/extjs/ext-2.0/ext-all.js"
></
script
>
<
script
type
="text/javascript"
src
="tree.js"
></
script
>
</
head
>
<
body
>
<
div
align
="center"
>
<
p
>
ExtJS-树的示例
</
p
>
</
div
>
<
div
id
="tree-div"
></
div
>
</
body
>
</
html
>
注意几个<script>标签,他们是用来引入ext的js以及本示例中用到的树。tree.js的代码如下:
Ext.BLANK_IMAGE_URL
=
'plugins
/
extjs
/
ext
-
2.0
/
resources
/
images
/
default
/
s.gif';
![](https://i-blog.csdnimg.cn/blog_migrate/1fa987a29c6482f53d401256f96355eb.gif)
Ext.onReady(
function
()
{
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
var tree = new Ext.tree.TreePanel(
{
el:"tree-div",
autoScroll:true,
animate:true,
width:'100px',
height:'300px',
enableDD:true,
containerScroll: true,
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
loader: new Ext.tree.TreeLoader(
{
dataUrl:'region.ejf?cmd=getRegion'
})
});
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
tree.on("click",function(node,event)
{alert(node.id);});
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
tree.on('beforeload',function(node)
{
tree.loader.dataUrl = 'region.ejf?cmd=getRegion&id='+(node.id!='root'?node.id:"");
});
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
var root = new Ext.tree.AsyncTreeNode(
{
text: '地区信息',
draggable:false,
id:'root'
});
tree.setRootNode(root);
tree.render();
root.expand();
}
);
其实tree.js的代码跟ExtJS官方示例中的差别不大,这里就不对这个代码作详细的解释,如果你感兴趣的话,可以在后面留言或给我发电子邮件。如果需要的人多的话,我看能否补充。这里把重点的代码强调一下。
loader:
new
Ext.tree.TreeLoader(
{
dataUrl:'region.ejf?cmd=getRegion'
}
)
这个表示通过region.ejf?cmd=getRegion来加载树的数据。另外,由于这里使用的是异步加载,所以还需要加下面一句:
tree.on('beforeload',
function
(node)
{
tree.loader.dataUrl = 'region.ejf?cmd=getRegion&id='+(node.id!='root'?node.id:"");
}
);
那么region.ejf?cmd=getRegion是做什么的呢?就是从数据库中查询地区数据,并把他转换成JSon格式就OK了。下面是RegionAction中的getRegion方法的代码,如下所示:
public
Page doGetRegion(WebForm form)
![](https://i-blog.csdnimg.cn/blog_migrate/1fa987a29c6482f53d401256f96355eb.gif)
{
String id=CommUtil.null2String(form.get("id"));
RegionQuery query=new RegionQuery();
query.setPageSize(-1);
if(!"".equals(id))
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
Region parent=this.service.getRegion(new Long(id));
query.setParent(parent);
}
IPageList pageList=this.service.getRegionBy(query);
List<Node> nodes=new java.util.ArrayList<Node>();
for(int i=0;i<pageList.getResult().size();i++)
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
Region region=(Region)pageList.getResult().get(i);
nodes.add(new Node(region));
}
form.addResult("json",AjaxUtil.getJSON(nodes));
return Page.JSONPage;
}
这个代码说白了,就是根据客户端的调用参数id值来加载该id下面的地区节点。RegionQuery是一个地区查询类,主要是我不想写sql或EJBQL,所以就用他了。大家主要看关键的部分,我们在调用service的getRegionBy方法返回的是一个分页的地区Entity。所以要把这个地区Entity转换成与Ext的树节点数据匹配的方式,因此就有了下面一段代码:
List
<
Node
>
nodes
=
new
java.util.ArrayList
<
Node
>
();
for
(
int
i
=
0
;i
<
pageList.getResult().size();i
++
)
![](https://i-blog.csdnimg.cn/blog_migrate/1fa987a29c6482f53d401256f96355eb.gif)
{
Region region=(Region)pageList.getResult().get(i);
nodes.add(new Node(region));
}
下面我们看看Node这个类的实现,代码如下:
private
class
Node
{
private Region region;
Node(Region region)
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
this.region=region;
}
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
public String getId()
{
return region.getId().toString();
}
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
public boolean getLeaf()
{
return region.getChildren().size()<1;
}
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
public String getText()
{
return region.getName();
}
public String getQtip()
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
{
return region.getName();
}
}
Node直接放在RegionAction中的,所以是Private的。这个Node所做的事就是把服务器的Region这个域模型适配成Ext的树状节点数据。在转换完以后,我们再看doGetRegion中的最后两句代码,如下所示:
form.addResult("json",AjaxUtil.getJSON(nodes));
return Page.JSONPage;
第一句代码是调用EasyJWeb中的AjaxUtil.getJSON方法直接把nodes这个List生成JSON数据;第二句告诉EasyJWeb这个模板使用的是JSONPage合成模板。呵呵,这个Page.JSONPage是这几天才加上去的,之前发布的m3没有,其实JSONPage模板的内容非常简单,内容如下:
function(){$!json}()
完成后,把这个Web应用打成war包,然后直接访问tree.html就能看到这个树了,大致如下图所示:
本示例已经被收录到了EasyJWeb的ajax综合示例中,里面还有更多的ajax示例,包括一个表格编辑的应用。
EasyJWeb的ajax综合示例的地址:http://easyjweb.demo.easyjf.com/ajax2/
本示例War包及源码:ftp://ftp1.easyjf.com/easyjweb/demo/ajax2.war (13M)
本示例的源码:ftp://ftp1.easyjf.com/easyjweb/demo/ajax2-src.zip (665K)
注:请下载后将db.properties里password改为你的密码。
你更希望我在“一起学ExtJS系列”中跟大家分享哪一方面的内容,请留言