2 Replies Latest reply on Jul 18, 2007 4:13 AM by Jonas Buechel

    UITree binding and other issues

    Christian Bauer Master

      You guys should use the Swing TreeModel/TreeNode combo and not invent your own model.

      The RichFaces TreeNode concept seems to be limited to exactly what the demo is doing - read an XML file and implement a separate class that represents the root node. I found no example with more dynamic tree adapters (what you usually do with a custom TreeModel in Swing).

      This is how it looks. Most people want lazy loading of children on the server. So what you need to support is this:

      - Composite Pattern: Node(Directory -to-many-> Document, Document)
      - The following code loads the root "node", imagine a C:/ directory
      - On-demand loading of subdirectories of C:/ and wrapping when the tree is expanded
      - No "files" are shown

       @Name("treeNodeAdapter")
       public static class TreeNodeAdapter {
      
       @Factory(value = "directoryTree", scope = ScopeType.CONVERSATION, autoCreate = true)
       public TreeNode loadReadableDirectoryTree() {
       Directory wikiroot = (Directory) Component.getInstance("wikiRoot");
       return new WikiTreeNode(wikiroot);
       }
      
       class WikiTreeNode implements TreeNode {
       private Node wikiNode;
       private Map<Object, TreeNode> childrenMap = new LinkedHashMap<Object,TreeNode>();
      
       public WikiTreeNode(Node wikiNode) {
       if (wikiNode != null) {
       this.wikiNode = wikiNode;
       for (Node childNode : wikiNode.getChildren()) {
       if (!WikiUtil.isDirectory(childNode)) continue;
       childrenMap.put(childNode.getId(), new WikiTreeNode(childNode));
       }
       }
       }
       public Object getData() { return wikiNode; }
       public void setData(Object node) { this.wikiNode = (Node)node; }
      
       public boolean isLeaf() {
       return childrenMap.size() == 0;
       }
       public Iterator getChildren() {
       return childrenMap.entrySet().iterator();
       }
       public TreeNode getChild(Object identifier) {
       return childrenMap.get( identifier );
       }
       public void addChild(Object identifier, TreeNode treeNode) {
       childrenMap.put(identifier, treeNode);
       }
       public void removeChild(Object identifier) {
       // Immutable
       }
      
       public TreeNode getParent() {
       return new WikiTreeNode(wikiNode.getParent());
       }
      
       public void setParent(TreeNode treeNode) {
       // Immutable
       }
       }
      
       }
      


      If you render #{directoryTree} with <rich:tree>, you get the C:/ ROOT shown - after all that is what is returned from this factory. There doesn't seem to be a way to hide the ROOT node. That wouldn't be really bad, what is bad is that you get a NullPointerException when you try to collapse the ROOT node. The rest of the tree seems to work fine (which is better than what I ever got in Icefaces or Oracle ADF after 2 hours of work).

      You should also as soon as possible extend the Tree documentation with an example for selection - nobody cares about drag and drop, people want to select a node first. Also, the word "cashing" is really spelled "caching".

      Please put this in an appropriate JIRA entry.

      Thanks


        • 1. Re: UITree binding and other issues
          Christian Bauer Master

          This works but please don't tell me that this is the only way:

           <rich:tree id="directoryTree" switchType="ajax"
           value="#{writableDirectoryTree}" var="d"
           style="margin: 10px;"
           icon="/themes/default/img/icon.dir.gif"
           iconLeaf="/themes/default/img/icon.dir.gif"
           selectedClass="activeTab"
           ajaxSubmitSelection="true"
           nodeSelectListener="#{documentHome.parentDirectorySelected}">
           <rich:treeNode>
           <h:outputText value="#{d.id} - #{d.name}"/>
           </rich:treeNode>
           </rich:tree>
          
          


           public void parentDirectorySelected(NodeSelectedEvent nodeSelectedEvent) {
           TreeRowKey rowkey = (TreeRowKey)((HtmlTree)nodeSelectedEvent.getSource()).getRowKey();
           Iterator pathIterator = rowkey.iterator();
           Long dirId = null;
           while (pathIterator.hasNext()) dirId = (Long)pathIterator.next();
           selectedDirectory = nodeDAO.findDirectory(dirId);
           }
          




          • 2. Re: UITree binding and other issues
            Jonas Buechel Novice

            Hi

            Is there a JIRA entry on this now?

            I'm wondering as well why there hasn't been used the "common" TreeModel as it is done in other rich JSF component libraries.

            I'm building a seam application which should display a tree. This tree will be the key point of the app.
            So i'm wondering if there will be some changes in the treemodel soon.

            I'm fighting with the same problems described in the following post:
            http://www.jboss.com/index.html?module=bb&op=viewtopic&t=112713

            Thanks for information!