用richFaces的<rich:treeNode>标签开发tree
岳乡成
环境:jdk1.6.0、jboss-4.2.3.GA、jboss-seam-2.1.1.GA 、My-SQL-5.0.8
一、标签说明
1. 概要
树形组件是最常用的组件之一,richFaces也实现了树形结构。<rich:treeNode>,<rich:recursiveTree>都适用于具有递归类型的数据结构,<rich:treeNode>的自由度更高。如下图所示为一个用<rich:treeNode>做的Tree的示例。
<rich:treeNode>示例
2. 标签属性
属性名称 描述
var Request范围内地循环变量
value 要生成Tree的所有节点的值
nodeSelectListener 节点选中监听事件
二、示例开发
1. JSF Web页面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<style>
.col, .col2 {
width:50%;
vertical-align:top;
}
</style>
<h:form>
<h:panelGrid columns="2" width="100%" columnClasses="col1,col2">
<rich:tree style="width:300px" nodeSelectListener="#{SimpleTreeBean.processSelection}"
reRender="selectedNode" ajaxSubmitSelection="true" switchType="client"
value="#{SimpleTreeBean.treeNode}" var="item" ajaxKeys="#{null}">
</rich:tree>
<h:outputText escape="false" value="#{SimpleTreeBean.selectedNodeDescription}" id="selectedNode" />
</h:panelGrid>
</h:form>
</ui:composition>
<rich:tree>标签中的reRender属性表示动态刷新id="selectedNode"的区域,
其他属性请参考上面的属性说明。
#{SimpleTreeBean.processSelection}中的SimpleTreeBean表示要绑定的Session Bean的name。
2. Session Bean及接口
Session Bean接口SimpleTreeBeanImpl如下:
package org.domain.seam.session.simpletree.Impl;
import java.util.List;
import javax.ejb.Local;
import org.domain.seam.session.entitybean.Treedirectory;
import org.richfaces.event.NodeSelectedEvent;
import org.richfaces.model.TreeNode;
@Local
public interface SimpleTreeBeanImpl {
public void processSelection(NodeSelectedEvent event) ;
public TreeNode getTreeNode() ;
public String getNodeTitle();
public void destroy();
public void addNodes(TreeNode node, List<Treedirectory> rootNode);
public List<String> getSelectedNodeChildren();
public String getSelectedNodeDescription();
public String getLeftnodecontext(int treedirectoryid);
}
Session Bean SimpleTreeBean如下:
/**
* <p>WeeklyPlanAction</p>
*
* 版权 (c) 2009
*
* <p>CIB</p>
*
* 文件历史
* 日期 作者 描述
* 2009-05-21 xiangcheng.yue 创建
*
*/
package org.domain.seam.session.simpletree;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.domain.seam.session.entitybean.Leftnodecontext;
import org.domain.seam.session.entitybean.Treedirectory;
import org.domain.seam.session.simpletree.Impl.SimpleTreeBeanImp;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.richfaces.component.html.HtmlTree;
import org.richfaces.event.NodeSelectedEvent;
import org.richfaces.model.TreeNode;
import org.richfaces.model.TreeNodeImpl;
/**
* 生成树目录结构,显示数据。
*
* @author xiangcheng.yue
* @version 1.0
*/
@Stateful
@Name("SimpleTreeBean")
/**
* 设置该Bean(SimpleTreeBean)的生命周期为Application,
* 目的是为了使该Bean在容器的整个生命周期一直存在。
*/
@Scope(ScopeType.APPLICATION)
public class SimpleTreeBean implements SimpleTreeBeanImp{
/** 根节点标志常量.*/
private static final int rootNodeFlag = 0;
/**实例化EntityManager。*/
@PersistenceContext
private EntityManager em;
/**生成的Tree。*/
private TreeNode rootNode = null;
/**选中节点的孩子结点List。*/
private List<String> selectedNodeChildren = new ArrayList<String>();
/**选中结点的名字。*/
private String nodeTitle;
/**选中结点的描述。*/
private String selectedNodeDescription;
public String getSelectedNodeDescription() {
return selectedNodeDescription;
}
public void setSelectedNodeDescription(String selectedNodeDescription) {
this.selectedNodeDescription = selectedNodeDescription;
}
public TreeNode getTreeNode() {
if (rootNode == null) {
loadTree();
}
return rootNode;
}
public String getNodeTitle() {
return nodeTitle;
}
public void setNodeTitle(String nodeTitle) {
this.nodeTitle = nodeTitle;
}
public List<String> getSelectedNodeChildren() {
return selectedNodeChildren;
}
public void setSelectedNodeChildren(List<String> selectedNodeChildren) {
this.selectedNodeChildren = selectedNodeChildren;
}
/**
* @since 2009-05-19
* 进入Tree页面时装入树所以的结点。
* @return void
* @throws
*/
private void loadTree() {
rootNode = new TreeNodeImpl();
/**通过根结点标志常量得到根节点list。*/
List<Treedirectory> results = getClildNodeList(rootNodeFlag);
if(results != null){
/**设置根结点的描述。*/
selectedNodeDescription = "";
/**向每个根节点加孩子结点。*/
addNodes(rootNode,results);
}
}
/**
* @since 2009-05-19
* 通过父节点得到该父结点的孩子结点list。
* @return List<Treedirectory>
* @throws
*/
public List<Treedirectory> getClildNodeList(int paratNode){
List<Treedirectory> results = em.createQuery("select td from Treedirectory td where td.parentid=" + paratNode).getResultList();
return results;
}
/**
* @since 2009-05-19
* 通过递归向每个节点添加孩子结点。
* @return TreeNode node, List<Treedirectory> rootNode
* @throws
*/
public void addNodes(TreeNode node, List<Treedirectory> rootNode) {
/**递归的出口标示,如果某个节点为孩子结点,该标示由false变为true,进行下一节点孩子结点的递归添加。*/
boolean end = false;
while(!end){
/**判断该节点是否有孩子结点。*/
if(rootNode.size()>0){
/**通过循环取出List<Treedirectory>中每个Treedirectory对象。*/
for(int i = 0;i<rootNode.size();i++){
/**实例化一个树的节点。*/
TreeNodeImpl nodeImpl = new TreeNodeImpl();
/**向该节点内设值。*/
nodeImpl.setData(rootNode.get(i).getNodename());
/**把节点加入树中,设置该节点的标志为该条数据在数据库中的Id。*/
node.addChild(new Integer(rootNode.get(i).getId()), nodeImpl);
/**递归调用。*/
addNodes(nodeImpl, getClildNodeList(rootNode.get(i).getId()));
}
}
end = true;
}
}
/**
* @since 2009-05-19
* 通过treedirectory table的Id得到leftnodecontext table中的leftcontext字段的内容。
* @return String
* @throws
*/
public String getLeftnodecontext(int treedirectoryid){
String leftnodecontext ="";
List<Leftnodecontext> results = em.createQuery("select td from Leftnodecontext td where td.treedirectoryid =" + treedirectoryid).getResultList();
if(results.size()>0){
Leftnodecontext lnc = results.get(0);
leftnodecontext = lnc.getLeftcontext();
}
return leftnodecontext;
}
/**
* @since 2009-05-19
* 点击每个结点触发的事件。
* @return NodeSelectedEvent event
* @throws
*/
public void processSelection(NodeSelectedEvent event) {
/**得到该Tree对象。*/
HtmlTree tree = (HtmlTree) event.getComponent();
/**得到点击的节点的值。*/
nodeTitle = (String) tree.getRowData();
/**清除selectedNodeChildren的内容。*/
selectedNodeChildren.clear();
TreeNode currentNode = tree.getModelTreeNode(tree.getRowKey());
if (currentNode.isLeaf()){
/**通过tree.getRowKey()得到该节点的Id。*/
String[] s = tree.getRowKey().toString().split(":");
int sLength = s.length;
int treeNodeId = Integer.parseInt(s[sLength-1]);
System.out.println("treeNodeId = "+treeNodeId);
/**得到该叶子节点在leftnodecontext table中的leftcontext.*/
String leftcontext = getLeftnodecontext(treeNodeId);
selectedNodeDescription = nodeTitle + " is a leafnode,it context is:" + leftcontext;
selectedNodeChildren.add((String)currentNode.getData());
}else
{
selectedNodeDescription = nodeTitle + " is not leaf,it have children node:";
Iterator<Map.Entry<Object, TreeNode>> it = currentNode.getChildren();
while (it!=null &&it.hasNext()) {
Map.Entry<Object, TreeNode> entry = it.next();
selectedNodeChildren.add(entry.getValue().getData().toString());
selectedNodeDescription = selectedNodeDescription + entry.getValue().getData().toString() + ";";
}
}
}
@Remove
public void destroy() {
}
}
以上代码主要是通过递归生成一个Tree,代码中都加上了详细的注解,看代码时请参考注解。
3. Entity Bean如下:
Treedirectory如下:
package org.domain.seam.session.entitybean;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.jboss.seam.annotations.Name;
@Entity
@Name("treedirectory")
public class Treedirectory implements Serializable
{
private int id;
private String nodename;
private int parentid;
private char leafflag;
@Id @GeneratedValue
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getNodename() {
return nodename;
}
public void setNodename(String nodename) {
this.nodename = nodename;
}
public int getParentid() {
return parentid;
}
public void setParentid(int parentid) {
this.parentid = parentid;
}
public char getLeafflag() {
return leafflag;
}
public void setLeafflag(char leafflag) {
this.leafflag = leafflag;
}
@Override
public String toString()
{
return "Treedirectory(" + nodename + "," + parentid + "," + leafflag + ")";
}
}
该Bean同数据库中的Treedirectory表相对应。
Leftnodecontext如下:
package org.domain.seam.session.entitybean;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.jboss.seam.annotations.Name;
@Entity
@Name("leftnodecontext")
public class Leftnodecontext implements Serializable
{
private int id;
private int treedirectoryid;
private String leftcontext;
@Id @GeneratedValue
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public int getTreedirectoryid() {
return treedirectoryid;
}
public void setTreedirectoryid(int treedirectoryid) {
this.treedirectoryid = treedirectoryid;
}
public String getLeftcontext() {
return leftcontext;
}
public void setLeftcontext(String leftcontext) {
this.leftcontext = leftcontext;
}
@Override
public String toString()
{
return "Leftnodecontext(" + leftcontext + ")";
}
}
该Bean同数据库中的Leftnodecontext表相对应。
4.添加jboss-web.xml配置文件。
richfaces 的 tree 选中节点等功能中需要用到 UI包中的 UITree 等,需要把richfaces-impl.jar,richfaces-ui.jar加到ear的jar的lib中,并在项目的web-inf中添加jboss-web.xml:
<!DOCTYPE jboss-web PUBLIC
"-//JBoss//DTD Web Application 4.2//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_4_2.dtd">
<jboss-web>
<class-loading java2ClassLoadingCompliance="false">
<loader-repository>
seam.jboss.org:loader=seamIntegration
<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>
5.小结。
利用richFaces的<rich:treeNode>标签过程非常简单,只需要掌握<rich:treeNode>的几个属性及深入理解递归的用法就可以了。希望参考本文档的读者能有所收获,谢谢。
分享到:
相关推荐
### <rich:listShuttle>标签使用 在JavaServer Faces (JSF)开发中,`rich:listShuttle`是RichFaces库中的一个非常实用的组件,主要用于实现列表项的双向选择和移动功能。例如,在用户界面中展示两个列表,并允许...
在JSF(JavaServer Faces)框架中,`<h:selectOneMenu>` 是一个用于创建下拉选择框的组件,而 `<a4j:support>` 是RichFaces库提供的一种Ajax支持的标签,它允许我们实现页面的部分更新,提高用户体验。这篇博客文章...
使用`<h:selectOneMenu>`标签开发级联选择涉及前端和后端的交互,理解JSF的核心概念,以及EL和Ajax在更新视图中的作用至关重要。通过适当的工具和技术,你可以创建出高效、响应式的级联选择功能,提升用户体验。
4. **创建JSF页面**:在`.xhtml`页面中,使用`<rich:tree>`标签来呈现树。例如: ```html <h:form> <rich:tree id="myTree" value="#{treeBean.rootNode}" var="node"> <rich:treeNode> <h:outputText value="#...
此外,还包括了如<rich:tree>、<rich:panel>、<rich:tabPanel>、<rich:fileUpload>等用于构建丰富用户交互界面的组件。 手册还列举了一些常见问题及其解决方法,如处理请求错误、会话过期、自定义样式、用户角色...
RichFaces的`<rich:dataTable>`和`<rich:extendedDataTable>`组件提供了强大的数据展示功能,支持分页、排序、过滤等操作。配合`<rich:datascroller>`可以实现数据的动态加载。 6. **国际化与本地化**: ...
### Richfaces标签详解 #### 一、概述 Richfaces是一个基于JavaServer Faces(JSF)技术的开源框架,提供了一套丰富的用户界面组件库。这些组件不仅具备强大的功能,还能很好地支持AJAX交互,极大地提高了Web应用...
通过添加`<rich:calendar>`标签,可以在列中添加日期选择功能: ```xml <rich:column> <f:facet name="header"> <h:outputText value="选择日期" /> </f:facet> <rich:calendar value="#{item.date}" ...
这里使用了`<h:outputText>`标签来显示表头文本,通过`styleClass`属性设置样式。 ##### 4. 显示数据 每列的具体数据通过`<h:column>`标签来定义,如: ```xml <h:column> <h:outputText value="#{car.name}"/> </...
在`richfaces`中,我们可以使用`<rich:dragSupport>`和`<rich:dropSupport>`这两个组件来实现。这两个组件分别用于定义可拖动的元素和接收拖动元素的目标区域。通过绑定拖放事件和定义数据交换逻辑,用户可以直观地...
1. **FileUpload组件**:RichFaces 提供了一个名为`<rich:fileUpload>`的组件,用于在Web页面上创建文件上传功能。这个组件允许用户选择本地文件并将其上传到服务器。`<rich:fileUpload>`提供了多种配置选项,如上传...
1. **组件的使用**:研究`<h:*>`和`<rich:*>`等标签,了解它们的属性和用法。 2. **数据绑定**:观察如何将组件与后台Bean的属性绑定,实现数据的双向传输。 3. **事件处理**:学习如何使用`<f:ajax>`或`<h:command...
`<rich:tabPanel>`用于创建带有多个标签页的面板,每个标签页可以包含不同的内容。用户可以使用AJAX切换标签,提供平滑的用户体验。 总结来说,A4J库提供了多种组件,帮助开发者构建富客户端的JSF应用,提升用户...
`rich:componentControl` 标签是 RichFaces 提供的一个非常实用的功能标签,主要用于控制其他 RichFaces 组件的行为。通过该标签,可以实现如显示/隐藏模态面板等操作。 - **属性解析**: - `for`:指定该控制作用...
RichFaces框架提供了丰富的客户端组件库,如`<rich:panel>`、`<a4j:commandButton>`等,它们增强了传统的JSF组件,提供了更丰富的用户界面和交互性。 综上所述,`rich:message`是RichFaces框架中用于处理验证错误...
1. **组件库**:RichFaces的组件库是其核心,包括但不限于数据表(`<rich:datascroller>`、`<rich:extendedDataTable>`)、对话框(`<rich:popupPanel>`)、时间选择器(`<rich:calendar>`)、文件上传(`<rich:...
- **Basic usage**:介绍如何使用 `<rich:graphValidator>` 来执行对象级别的验证。 以上就是对“Richfaces 4 组件参考手册”的详细解析,希望能够帮助读者更好地理解和使用Richfaces 4 的各项功能。
2. **丰富的组件库**:RichFaces提供了大量预先封装的UI组件,如`<rich:calendar>`用于日期选择,`<rich:slider>`用于滑动选择,以及`<rich:tabPanel>`用于多标签视图。这些组件大大减少了开发者自定义组件的工作量...
总结起来,要在JSF 1.2中实现迭代和循环,可以使用`<ui:repeat>`标签,结合Managed Bean中的集合属性。同时,通过`<f:ajax>`实现Ajax交互,提升用户体验。如果项目需要模仿Struts的迭代方式,理解JSF的EL和组件模型...