RichFaces - Arbre riche
Dans ce chapitre, nous allons découvrir le traitement des arbres dans RichFaces. RichFaces fournit tous les composants nécessaires pour créer et manipuler un arbre.
<rich: treeNode>
Cette balise est utilisée pour créer une arborescence hiérarchique. Chaque nœud fourni à l'intérieur du <treeNode> sera un nœud enfant de l'arborescence. Cette balise sera utilisée avec une autre balise appelée <rich: tree>. Toutes les variables d'instance que nous utilisons pour créer un arbre doivent implémenter l'une de ces trois interfaces -org.richfaces.model.TreeNode, org.richfaces.model.TreeDataModel, et javax.swing.tree.TreeNode.
Dans l'exemple suivant, nous remplirons une arborescence à l'aide de la balise <rich: treeNode> du backend.
<?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>
Voici la classe Java associée qui implémente “TreeNodeImpl” interface.
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;
}
}
Le morceau de code ci-dessus produira la sortie suivante dans le navigateur.
<rich: treeModelAdaptor>
Ce composant prend une carte comme entrée, l'itère et produit la sortie requise dans le navigateur. Chaque fois que nous avons besoin de remplir une carte récursive, nous pouvons utiliser une autre balise appelée<rich:recursiveTreeModelAdaptor>.
L'exemple suivant montre comment rendre la structure du projet dans le navigateur. Dans RichFaces 3, ces deux balises sont utilisées <rich: treeNodeAdaptor> et <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>
Nous devons créer deux nouveaux beans java pour cet exemple. Voici l'extrait de code de la classe de bean «FileSystemBean.java», qui contient le nom de dossier requis.
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;
}
}
Voici l'extrait de code de la classe de bean «FileSystemNode.java», qui contient le nœud feuille requis du projet.
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;
}
}
L'exemple ci-dessus produira la sortie suivante dans le navigateur.