RichFaces - 丰富的树
在本章中,我们将学习 RichFaces 中的树处理。RichFaces 提供创建和操作树所需的所有组件。
<丰富:树节点>
该标签用于创建层次树。<treeNode> 内提供的每个节点都将是树的子节点。该标签将与另一个名为 <rich:tree> 的标签一起使用。我们用来创建树的所有实例变量都必须实现这三个接口中的任何一个 - org.richfaces.model.TreeNode、org.richfaces.model.TreeDataModel和javax.swing.tree.TreeNode。
在下面的示例中,我们将使用后端的 <rich:treeNode> 标签填充一棵树。
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE html> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:h = "http://java.sun.com/jsf/html" xmlns:f = "http://java.sun.com/jsf/core" xmlns:ui = "http://java.sun.com/jsf/facelets" xmlns:a4j = "http://richfaces.org/a4j" xmlns:rich = "http://richfaces.org/rich"> <h:head> <title>TreeNode Example</title> <meta name = "viewport" content = "width = device-width, initial-scale = 1.0"/> </h:head> <h:body> <h:form> <rich:tree value = "#{tree.populateNode}" var = "tree"> <rich:treeNode> <rich:treeModelRecursiveAdaptor> </rich:treeModelRecursiveAdaptor> <h:outputText value = "#{tree.data}" /> </rich:treeNode> </rich:tree> </h:form> </h:body> </html>
以下是实现“TreeNodeImpl”接口的相关java类。
import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; import org.richfaces.model.TreeNodeImpl; @ManagedBean @RequestScoped public class Tree extends TreeNodeImpl { private Tree stationRoot; private Tree populateNode; private Object data; public Tree() { super(); } public Tree(boolean leaf, Object data) { super(leaf); this.data = data; } public Object getData() { return data; } public Tree getPopulateNode() { if (populateNode == null) { String[] List_OF_Node = { "Frist Node", "Second Node", "Third Node", "Fourth Node", "Fifth Node"}; stationRoot = new Tree(false, "Example Of Tree"); for (int i = 0; i < List_OF_Node.length; i++) { Tree child = new Tree(true, List_OF_Node[i]); stationRoot.addChild(i, child); } populateNode = new Tree(); populateNode.addChild(0, stationRoot); } return populateNode; } }
上面的代码将在浏览器中产生以下输出。
<丰富:树模型适配器>
该组件将 Map 作为输入,对其进行迭代,并在浏览器中生成所需的输出。每当我们需要填充递归映射时,我们可以使用另一个名为<rich:recursiveTreeModelAdaptor>的标签。
以下示例展示了如何在浏览器中呈现项目结构。在RichFaces 3中,使用了这两个标签<rich:treeNodeAdaptor>和<rich:recursiveTreeNodeAdaptor>。
<?xml version = "1.0" encoding = "UTF-8"?> <!DOCTYPE html> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:h = "http://java.sun.com/jsf/html" xmlns:f = "http://java.sun.com/jsf/core" xmlns:ui = "http://java.sun.com/jsf/facelets" xmlns:a4j = "http://richfaces.org/a4j" xmlns:rich = "http://richfaces.org/rich"> <h:head> <title>Tree Model and Recursive Model Example</title> </h:head> <h:body> <h:form id = "form"> <rich:tree toggleType = "AJAX" var = "item" style = "max-width: 400px"> <rich:treeModelRecursiveAdaptor roots = "#{fileSystemBean.sourceRoots}" nodes = "#{item.directories}"> <rich:treeNode> #{item.shortPath} </rich:treeNode> <rich:treeModelAdaptor nodes = "#{item.files}"> <rich:treeNode>#{item}</rich:treeNode> </rich:treeModelAdaptor> </rich:treeModelRecursiveAdaptor> </rich:tree> </h:form> </h:body> </html>
我们需要为此示例创建两个新的 java bean。以下是 bean 类“FileSystemBean.java”的代码片段,其中包含所需的文件夹名称。
import java.util.List; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @ManagedBean @RequestScoped public class FileSystemBean { private static final String SRC_PATH = "/WEB-INF"; private List<FileSystemNode> srcRoots; public synchronized List<FileSystemNode> getSourceRoots() { if (srcRoots == null) { srcRoots = new FileSystemNode(SRC_PATH).getDirectories(); } return srcRoots; } }
以下是 bean 类“FileSystemNode.java”的代码片段,它保存项目所需的叶节点。
import static com.google.common.base.Predicates.containsPattern; import static com.google.common.base.Predicates.not; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.transform; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import com.google.common.base.Function; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; public class FileSystemNode { private static final Function<String, FileSystemNode> FACTORY = new Function<String, FileSystemNode>() { public FileSystemNode apply(String from) { return new FileSystemNode(from.substring(0, from.length() - 1)); }; }; private static final Function<String, String> TO_SHORT_PATH = new Function<String, String>() { public String apply(String from) { int idx = from.lastIndexOf('/'); if (idx < 0) { return from; } return from.substring(idx + 1); }; }; private String path; private List<FileSystemNode> directories; private List<String> files; private String shortPath; public FileSystemNode(String path) { this.path = path; int idx = path.lastIndexOf('/'); if (idx != -1) { shortPath = path.substring(idx + 1); } else { shortPath = path; } } public synchronized List<FileSystemNode> getDirectories() { if (directories == null) { directories = Lists.newArrayList(); Iterables.addAll(directories, transform(filter( getResourcePaths(), containsPattern("/$")), FACTORY)); } return directories; } public synchronized List<String> getFiles() { if (files == null) { files = new ArrayList<String>(); Iterables.addAll(files, transform(filter( getResourcePaths(), not(containsPattern("/$"))), TO_SHORT_PATH)); } return files; } private Iterable<String> getResourcePaths() { FacesContext facesContext = FacesContext.getCurrentInstance(); ExternalContext externalContext = facesContext.getExternalContext(); Set<String> resourcePaths = externalContext.getResourcePaths(this.path); if (resourcePaths == null) { resourcePaths = Collections.emptySet(); } return resourcePaths; } public String getShortPath() { return shortPath; } }
上面的示例将在浏览器中产生以下输出。