`
岳乡成
  • 浏览: 122024 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

用richFaces的<rich:treeNode>标签开发tree

阅读更多
  用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>的几个属性及深入理解递归的用法就可以了。希望参考本文档的读者能有所收获,谢谢。
分享到:
评论

相关推荐

    标签使用

    ### &lt;rich:listShuttle&gt;标签使用 在JavaServer Faces (JSF)开发中,`rich:listShuttle`是RichFaces库中的一个非常实用的组件,主要用于实现列表项的双向选择和移动功能。例如,在用户界面中展示两个列表,并允许...

    <h:selectOneMenu>与<a4j:support>的集合运用(JSF)

    在JSF(JavaServer Faces)框架中,`&lt;h:selectOneMenu&gt;` 是一个用于创建下拉选择框的组件,而 `&lt;a4j:support&gt;` 是RichFaces库提供的一种Ajax支持的标签,它允许我们实现页面的部分更新,提高用户体验。这篇博客文章...

    用selectOneMenu标签开发级联选择

    使用`&lt;h:selectOneMenu&gt;`标签开发级联选择涉及前端和后端的交互,理解JSF的核心概念,以及EL和Ajax在更新视图中的作用至关重要。通过适当的工具和技术,你可以创建出高效、响应式的级联选择功能,提升用户体验。

    使用richfaces 实现tree

    4. **创建JSF页面**:在`.xhtml`页面中,使用`&lt;rich:tree&gt;`标签来呈现树。例如: ```html &lt;h:form&gt; &lt;rich:tree id="myTree" value="#{treeBean.rootNode}" var="node"&gt; &lt;rich:treeNode&gt; &lt;h:outputText value="#...

    Richfaces 常用组件使用手册中文版

    此外,还包括了如&lt;rich:tree&gt;、&lt;rich:panel&gt;、&lt;rich:tabPanel&gt;、&lt;rich:fileUpload&gt;等用于构建丰富用户交互界面的组件。 手册还列举了一些常见问题及其解决方法,如处理请求错误、会话过期、自定义样式、用户角色...

    richfaces组件说明文档及使用实例

    RichFaces的`&lt;rich:dataTable&gt;`和`&lt;rich:extendedDataTable&gt;`组件提供了强大的数据展示功能,支持分页、排序、过滤等操作。配合`&lt;rich:datascroller&gt;`可以实现数据的动态加载。 6. **国际化与本地化**: ...

    Richfaces标签

    ### Richfaces标签详解 #### 一、概述 Richfaces是一个基于JavaServer Faces(JSF)技术的开源框架,提供了一套丰富的用户界面组件库。这些组件不仅具备强大的功能,还能很好地支持AJAX交互,极大地提高了Web应用...

    Richfaces的DateTable

    通过添加`&lt;rich:calendar&gt;`标签,可以在列中添加日期选择功能: ```xml &lt;rich:column&gt; &lt;f:facet name="header"&gt; &lt;h:outputText value="选择日期" /&gt; &lt;/f:facet&gt; &lt;rich:calendar value="#{item.date}" ...

    richfaces中的datagrid显示数据

    这里使用了`&lt;h:outputText&gt;`标签来显示表头文本,通过`styleClass`属性设置样式。 ##### 4. 显示数据 每列的具体数据通过`&lt;h:column&gt;`标签来定义,如: ```xml &lt;h:column&gt; &lt;h:outputText value="#{car.name}"/&gt; &lt;/...

    richfaces3.3.1实现表格的行拖动、分页加载等功能

    在`richfaces`中,我们可以使用`&lt;rich:dragSupport&gt;`和`&lt;rich:dropSupport&gt;`这两个组件来实现。这两个组件分别用于定义可拖动的元素和接收拖动元素的目标区域。通过绑定拖放事件和定义数据交换逻辑,用户可以直观地...

    JSF+rich 实现 fileUpload

    1. **FileUpload组件**:RichFaces 提供了一个名为`&lt;rich:fileUpload&gt;`的组件,用于在Web页面上创建文件上传功能。这个组件允许用户选择本地文件并将其上传到服务器。`&lt;rich:fileUpload&gt;`提供了多种配置选项,如上传...

    jsf 中文Demo 本人付出研究一个月的Demo 请认真学习一下

    1. **组件的使用**:研究`&lt;h:*&gt;`和`&lt;rich:*&gt;`等标签,了解它们的属性和用法。 2. **数据绑定**:观察如何将组件与后台Bean的属性绑定,实现数据的双向传输。 3. **事件处理**:学习如何使用`&lt;f:ajax&gt;`或`&lt;h:command...

    Usage of A4J.Usage of A4J.Usage of A4J.

    `&lt;rich:tabPanel&gt;`用于创建带有多个标签页的面板,每个标签页可以包含不同的内容。用户可以使用AJAX切换标签,提供平滑的用户体验。 总结来说,A4J库提供了多种组件,帮助开发者构建富客户端的JSF应用,提升用户...

    richface标签.doc

    `rich:componentControl` 标签是 RichFaces 提供的一个非常实用的功能标签,主要用于控制其他 RichFaces 组件的行为。通过该标签,可以实现如显示/隐藏模态面板等操作。 - **属性解析**: - `for`:指定该控制作用...

    rich:message使用方法

    RichFaces框架提供了丰富的客户端组件库,如`&lt;rich:panel&gt;`、`&lt;a4j:commandButton&gt;`等,它们增强了传统的JSF组件,提供了更丰富的用户界面和交互性。 综上所述,`rich:message`是RichFaces框架中用于处理验证错误...

    jsf 里面richfaces 开发包

    1. **组件库**:RichFaces的组件库是其核心,包括但不限于数据表(`&lt;rich:datascroller&gt;`、`&lt;rich:extendedDataTable&gt;`)、对话框(`&lt;rich:popupPanel&gt;`)、时间选择器(`&lt;rich:calendar&gt;`)、文件上传(`&lt;rich:...

    Richfaces 4 组件参考手册

    - **Basic usage**:介绍如何使用 `&lt;rich:graphValidator&gt;` 来执行对象级别的验证。 以上就是对“Richfaces 4 组件参考手册”的详细解析,希望能够帮助读者更好地理解和使用Richfaces 4 的各项功能。

    jsf最新版本jar包跟richfaces4.0完美结合

    2. **丰富的组件库**:RichFaces提供了大量预先封装的UI组件,如`&lt;rich:calendar&gt;`用于日期选择,`&lt;rich:slider&gt;`用于滑动选择,以及`&lt;rich:tabPanel&gt;`用于多标签视图。这些组件大大减少了开发者自定义组件的工作量...

    用JSF1.2实现迭代,循环标签(还是组件?)

    总结起来,要在JSF 1.2中实现迭代和循环,可以使用`&lt;ui:repeat&gt;`标签,结合Managed Bean中的集合属性。同时,通过`&lt;f:ajax&gt;`实现Ajax交互,提升用户体验。如果项目需要模仿Struts的迭代方式,理解JSF的EL和组件模型...

Global site tag (gtag.js) - Google Analytics