El componente tree2 de MyFaces

MyFaces se una implementación GPL de las librerí­as Java Server Faces de Sun Microsystems. Cuenta con un número importante de componentes añadidos que evitan al programador el trabajo de crearlas. Uno de ellos es el de los “árboles”, que puede verse en la imagen de abajo:

tree2

Resulta que me encuentro con la necesidad de implementar un árbol deslpegable y voy a la documentación de MyFaces donde busco el componente Tree2 (olvidemos el Tree “uno” que es menos interesante). La documentación deberí­a estar ahí­: http://myfaces.apache.org/tomahawk/tree2.html. Pero para mi sorpresa, la documentación es inexistente.

Después de media mañana perdida, descubro varios weblogs donde se explica someramente el proceso. Mi intención es explicarlo aquí­ con un poco más de detalle y en español para que quede constancia ;-) .

Prerequisitos

  • Tomcat instalado y funcionando y capacidad de despliege de aplicaciones.
  • Una estructura de directorios correcta: WEB-INF conteniendo lib y classes.
  • El filtro de extensiones de MyFaces configurado en el web.xml. Supondré que actúa sobre los mismos elementos que el FacesServlet (/faces/*).

En primer lugar hay que pensar en la estructura del árbol. En este caso vamos a analizar una estructura simple. Consta de una compañí­a (company), que tiene como “hijos” los departamentos (department) Programacion y Diseño. Dentro de cada departamento puede haber personas (person) o cosas (thing). Los nombres en inglés entre paréntesis son lso identificadores que habrá que usar al crear la estructura del árbol y al indicársela al componente tree2 de MyFaces. Empecemos por esto último.

Para especificar los elementos de que consta el árbol es necesario entre los tags de <x:tree> y </x:tree> situar un <f:facelet> por cada elemento. Como en el siguiente ejemplo:


<t:tree2 value="#{treeBean.treeData}" var="node" clientSideToggle="true">
  <f:facet name="company">
    <h:panelGroup>
      <t:graphicImage value="images/tree/yellow-folder-open.png" styleClass="iconImage"/>
      <h:outputText value="#{node.description}" styleClass="label"/>
    </h:panelGroup>
  </f:facet>
                                           
  <f:facet name="departemt">
    <h:panelGroup>
      <t:graphicImage value="images/tree/yellow-folder-open.png" styleClass="iconImage"/>
      <h:outputText value="#{ node.description}" styleClass="label"/>
    </h:panelGroup>
  </f:facet>
                                           
  <f:facet name="person">
    <h:panelGroup>
      <t:graphicImage value="images/tree/yellow- folder-open.png" styleClass="iconImage"/>
      <h:outputText value="#{node.description}" styleClass="simpleText"/>
    </h:panelGroup>
  </f:facet>

  <f:facet name="thing">
    <h:panelGroup>
      <t:graphicImage value="images/tree/yellow-folder-open.png" styleClass="iconImage"/>
      <h:outputText value="#{ node.description}" styleClass="simpleText"/>
    </h:panelGroup>
  </f:facet>
                                           
</t:tree2>                                                                   

Hay que fijarse principalmente en el atributo “name” de los facets. Esos valores serán los valores que se podrán especificar al crear en la estructura del árbol.

Las opciones de los facets anteriores pueden estar mucho más elaborados (commandLinks, varias imágenes que pueden cambiar, etc). Sin embargo en el presente ejemplo nos conformamos con una imagen para cada elemento (images/tree/yellow- folder-open.png) y un texto que tiene como valor “#{node.description}”. Esto significa que al mostrar ese elemento, se mostrará el texto de su descripción. La descripción de cada elemento está almacenada en la estructura del árbol. La estructura del árbol debe estar almacenada en un Bean que en el ejemplo se llama treeBean. Ese Bean debe tener un método (en el ejemplo getTreeData()) que permita obtener la estructura del árbol. El objetivo siguiente es hacer ese Bean y definirlo en el faces-config.xml.

Añadimos lo siguiente en faces-config.xml para hacer el Bean accesible a la página JSF.


    <managed-bean>
        <managed-bean-name>treeBean</managed-bean-name>
        <managed-bean-class>tree.TreeModelBean</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>

El siguiente código es el código más sencillo para devolver una estructura de árbol. Es muy ineficiente y no deberí­a ser usado para producción. Lo ideal serí­a crear la estructura del árbol desde un fichero xml y almacenarla en un Bean accesible por toda la aplicación, o que se recuperara mediante una llamada a EJB.

Paso a comentar el código. Se puede ver que el bean sólo dispone de un método de devuelve un TreeNode, este TreeNode que devolveremos al final del método es el nodo raí­z (root) del árbol y de él cuelgan todos los demás elementos. Lo creamos instanciando un nuevo TreeNodeBase y le damos un “tipo de elemento”, que debe coincidir con el nombre de un facet; una descripción y un boolean que indica si es un nodo terminal (true) o no (false).

A continuación vamos rellenando una estructura de hijos llamando al método add() de la lista que devuelve el método getChildren() de los TreeNode.
Por último devolvemos el TreeNode root.


package tree;

import org.apache.myfaces.custom.tree2.TreeNode;
import org.apache.myfaces.custom.tree2.TreeNodeBase;

public class TreeModelBean {

    public TreeNode getTreeData() {
        TreeNode root = new TreeNodeBase("company","Krube - Informatica para todos",false);
       
        TreeNode child = new TreeNodeBase("departemt", "Programacion","d1",false);
        TreeNode pChild = new TreeNodeBase("person", "David","p1",true);
        child.getChildren().add(pChild);
        pChild = new TreeNodeBase("thing","Ordenador", "t1", true);
        child.getChildren().add(pChild);
       
        TreeNode child2 = new TreeNodeBase("department", "Diseño", "d2", false);
        TreeNode pChild2 = new TreeNodeBase("person", "Juana", "p2", true);
        child2.getChildren().add(pChild2);
        pChild2 = new TreeNodeBase("thing", "Pincel", "t2", true);
        child2.getChildren().add(pChild2);       
       
        root.getChildren().add(child);
        root.getChildren().add(child2);
       
        return root;
    }
}

Si todo ha ido bien, el tree2 está listo y ya podemos dedicarnos a usarlo para algo de verdad. Espero que haya servidod de ayuda.

Posted By dsuarez

David nació en Las Palmas de Gran Canaria, España. Estudió Ingeniería en Informática en la Universidad de Las Palmas de Gran Canaria (ULPGC), donde ha trabajado en investigación los últimos años. Siempre ha sentido una gran curiosidad por los ordenadores y las ciencias, y más recientemente en el mundo empresarial. Ha trabajado como programador/analista, consultor en tecnologías de la información y obtuvo la beca de Google Summer of Code en 2006. Es socio fundador de Wantudu (http://wantudu.es), empresa especializada en terminales táctiles para hoteles.

5 Responses to “El componente tree2 de MyFaces”

  1. Miguel Angel says:

    Hola soy nuevo en todo esto de las Myfaces y todavia no lo controlamos como le añadiris tu un evento al arbolo para que cuando hagas click en un nodo del arbol te muestre por ejemplo al lado un formulario distinto cada vez que pulsas un nodo distinto.

    Muchisimas Gracias.

  2. Boris Perez says:

    Bueno… listo eso, pero y ahora cómo se hace para ponerle un ví­nculo al elemento final de un árbol ?

    Gracias

  3. Bruno says:

    Hola, hice todos los pasos que muestras anteriormente pero obtengo un problema con el web.xml. Agradeceria me pudieras brindas la configuracion correcta del web.xml. Gracias!

  4. Alb says:

    ¿Cómo puedo hacer para que sea un árbol de checkboxes dinámicamente? Es decir, construir un árbol dinámicamente, en donde cada nodo sea un checkbox.
    Gracias!

  5. Juan Altamirano says:

    yo logre construir un arbol con una clase recursiva en java, que tenia como atributos adicionales padre(del mismo tipo de la clase) e hijos(una lista del mismo tipo de la clase tambien)
    Pero ahora no se como hacer para manejar el nodo de la seleccion de un nodo. ayudaa plx!!

Leave a Reply