2 Replies Latest reply on Apr 11, 2008 5:12 PM by Mark LoSacco

    rich:tree reRender of tree does not repopulate tree

    Mark LoSacco Newbie

      I have a page that allows a user to manipulate a tree control via a set of toolbar buttons (add top level node, add child node, delete node, etc).

      The tree is properly re-drawn when I delete nodes and when I edit nodes (for example edit the node text). But I can't seem to force the tree to display newly added nodes.

      I have tried using both ajax reRender on the parent panel containing the tree control, on the tree control itself, and even tried doing a redirect back to the page. A page refresh also does not force the rendering of new nodes.

      But leaving the page entirely and coming back in through an external link does of course cause the tree to be correctly displayed. So the nodes are definitely there in my underlying data model.

      Hoping someone can point me in right direction.

      I am using latest Seam and Rich Faces 3.2.0.
      Thanks to devs for latest update - fixed one problem I was having when last node in tree was deleted.

      The relevant code is below.

      -Mark

      Here is the page:

       <rich:panel id="pagetree">
       <f:facet name="header">#{messages['com.leagueunited.admin.pages']}</f:facet>
       <h:form>
      
       <rich:toolBar id="treetb" height="26" itemSeparator="line">
       <rich:toolBarGroup>
       <h:commandLink action="#{webPageTreeAction.addMenutab}">
       <h:graphicImage styleclass="toolbarimg" value="img/newtab.png"
       alt="Create Tab" />
       </h:commandLink>
      
       </rich:toolBarGroup>
      
       </rich:toolBar>
      
       <rich:tree switchType="client" ajaxSubmitSelection="true"
       reRender="treetb, pageeditor, globalMessages">
      
       <rich:treeNodesAdaptor id="tab" nodes="#{sport.menutabs}"
       var="_tab">
       <rich:treeNode data="#{_tab.menutabId}"
       nodeSelectListener="#{webPageTreeAction.processMenutabSelection}">
       <h:outputText value="#{_tab.menutabCaption}" />
       </rich:treeNode>
      
       <rich:recursiveTreeNodesAdaptor id="page" var="_page"
       roots="#{_tab.menupages}" includedRoot="#{_page.topPage}"
       nodes="#{_page.subMenupages}">
      
       <rich:treeNode data="#{_page.menupageId}"
       nodeSelectListener="#{webPageTreeAction.processMenupageSelection}">
       <h:outputText value="#{_page.menupageCaption}" />
       </rich:treeNode>
      
       </rich:recursiveTreeNodesAdaptor>
       </rich:treeNodesAdaptor>
       </rich:tree>
       </h:form>
       </rich:panel>
      


      And here is the bean:
      @Name("webPageTreeAction")
      @Scope(ScopeType.EVENT)
      public class WebPageTreeActionBean {
      
       @Logger private Log log;
      
       @In
       @Out
       protected MenutabHome menutabHome;
      
       @In
       @Out
       protected MenupageHome menupageHome;
      
       @In
       protected SportHome sportHome;
      
       @In protected FacesMessages facesMessages;
      
       public boolean isPageSelected() {
       return (menupageHome.isManaged());
       }
      
       public boolean isTabSelected() {
       return (!menupageHome.isManaged() && menutabHome.isManaged());
       }
      
       public void addMenutab() {
       Menutab tab = new Menutab(sportHome.getInstance(), "New Tab", (byte) 0);
       tab.setMenutabType(MenutabType.MENUTAB_CUSTOM);
       menutabHome.setInstance(tab);
       menutabHome.persist();
       }
      
      
       public void processMenutabSelection(NodeSelectedEvent event) {
       UITreeNode treeNode = (UITreeNode) event.getComponent();
       Integer menutabId = (Integer) treeNode.getData();
      
       log.info("processMenutabSelection Called!!!!!!! " + menutabId.toString());
       menutabHome.setId(menutabId);
      
       menutabHome.wire();
       menupageHome.clearInstance();
       log.info("menutab Caption: " + menutabHome.getInstance().getMenutabCaption());
      
       facesMessages.clear();
       }
      
       public void processMenupageSelection(NodeSelectedEvent event) {
       UITreeNode treeNode = (UITreeNode) event.getComponent();
       Integer menupageId = (Integer) treeNode.getData();
      
       log.info("processMenupageSelection Called!!!!!!! " + menupageId.toString());
       menupageHome.setId(menupageId);
       menutabHome.setId(menupageHome.getInstance().getMenutab().getMenutabId());
      
       menutabHome.wire();
       menupageHome.wire();
       log.info("menupage Caption: " + menupageHome.getInstance().getMenupageCaption());
       }
      


        • 1. Re: rich:tree reRender of tree does not repopulate tree
          Nick Belaevski Master

          Hello,

          I couldn't run the code (Menutab class is missing), so I've tried to create my own version of the code. Here it is:

          <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
          <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
          
          <%@ taglib uri="http://labs.jboss.com/jbossrichfaces/ui/treeModel" prefix="model" %>
          <%@ taglib uri="http://labs.jboss.com/jbossrichfaces/ui/tree" prefix="tree" %>
          <%@ taglib uri="http://richfaces.org/a4j" prefix="a4j" %>
          
          <html>
           <head>
           <title></title>
           </head>
           <body>
           <f:view>
           <h:form>
           <a4j:outputPanel ajaxRendered="true">
           <h:messages />
           </a4j:outputPanel>
          
           <h:inputText required="true" value="val"/>
          
           <a4j:commandLink value="Add nodes..." reRender="tree" action="#{treeModelBean.add}" />
          
           <tree:tree adviseNodeOpened="#{treeModelBean.adviseNodeOpened}" switchType="client" id="tree">
           <model:treeNodesAdaptor id="project" nodes="#{loaderBean.projects}" var="project">
           <tree:treeNode>
           <a4j:commandLink action="#{project.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{project.click}" value="Project: #{project.name}" />
           </tree:treeNode>
          
           <model:treeNodesAdaptor id="srcDir" var="srcDir" nodes="#{project.srcDirs}">
           <tree:treeNode>
           <a4j:commandLink action="#{srcDir.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{srcDir.click}" value="Source directory: #{srcDir.name}" />
           </tree:treeNode>
          
           <model:treeNodesAdaptor id="pkg" var="pkg" nodes="#{srcDir.packages}">
           <tree:treeNode>
           <a4j:commandLink action="#{pkg.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{pkg.click}" value="Package: #{pkg.name}" />
           </tree:treeNode>
          
           <model:treeNodesAdaptor id="class" var="class" nodes="#{pkg.classes}">
           <tree:treeNode>
           <a4j:commandLink action="#{class.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{class.click}" value="Class: #{class.name}" />
           </tree:treeNode>
           </model:treeNodesAdaptor>
           </model:treeNodesAdaptor>
          
           <model:treeNodesAdaptor id="pkg1" var="pkg" nodes="#{srcDir.packages}">
           <tree:treeNode>
           <a4j:commandLink action="#{pkg.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{pkg.click}" value="Package1: #{pkg.name}" />
           </tree:treeNode>
          
           <model:treeNodesAdaptor id="class1" var="class" nodes="#{pkg.classes}">
           <tree:treeNode>
           <a4j:commandLink action="#{class.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{class.click}" value="Class1: #{class.name}" />
           </tree:treeNode>
           </model:treeNodesAdaptor>
           </model:treeNodesAdaptor>
           </model:treeNodesAdaptor>
          
           <model:recursiveTreeNodesAdaptor id="dir" var="dir"
           roots="#{project.dirs}" nodes="#{dir.directories}">
           <tree:treeNode>
           <a4j:commandLink action="#{dir.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{dir.click}" value="Directory: #{dir.name}" />
           </tree:treeNode>
          
           <model:treeNodesAdaptor id="file" var="file" nodes="#{dir.files}">
           <tree:treeNode>
           <a4j:commandLink action="#{file.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{file.click}" value="File: #{file.name}" />
           </tree:treeNode>
           </model:treeNodesAdaptor>
          
           <model:treeNodesAdaptor id="file1" var="file" nodes="#{dir.files}">
           <tree:treeNode>
           <a4j:commandLink action="#{file.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{file.click}" value="File1: #{file.name}" />
           </tree:treeNode>
           </model:treeNodesAdaptor>
          
           <model:recursiveTreeNodesAdaptor id="archiveEntry" var="archiveEntry"
           roots="#{dir.files}" nodes="#{archiveEntry.archiveEntries}"
           includedRoot="#{archiveEntry.class.simpleName == 'ArchiveFile'}"
           includedNode="#{archiveEntry.class.simpleName == 'ArchiveEntry'}">
          
           <tree:treeNode id="archiveEntryNode">
           <a4j:commandLink action="#{archiveEntry.click}" ajaxSingle="true" value="Immediate " />
           <br />
           <h:commandLink action="#{archiveEntry.click}" value="Archive entry: #{archiveEntry.name}" />
           </tree:treeNode>
          
           </model:recursiveTreeNodesAdaptor>
          
           </model:recursiveTreeNodesAdaptor>
          
           <%--model:treeNodes var="file" nodes="#{proj.dir.files}">
           <tree:treeNode>
           <h:outputText value="File: #{file.name}" />
           </tree:treeNode>
           </model:treeNodes--%>
           </model:treeNodesAdaptor>
           </tree:tree>
          
           <tree:tree adviseNodeOpened="#{treeModelBean.adviseNodeOpened}" switchType="client">
           <model:recursiveTreeNodesAdaptor roots="#{treeModelBean.simpleResursiveNodes}" var="node" nodes="#{node.children}">
           <tree:treeNode>
           <h:commandLink value="#{node.text}" action="#{node.remove}" />
           </tree:treeNode>
           </model:recursiveTreeNodesAdaptor>
           </tree:tree>
           </h:form>
           </f:view>
           </body>
          </html>


          /**
           *
           */
          package org.richfaces;
          
          import java.util.List;
          import java.util.Map;
          import java.util.UUID;
          
          import javax.faces.context.FacesContext;
          
          import org.richfaces.component.UITree;
          import org.richfaces.model.Directory;
          import org.richfaces.model.File;
          import org.richfaces.model.Project;
          import org.richfaces.model.SimpleRecursiveNode;
          import org.richfaces.service.Loader;
          
          /**
           * @author Nick Belaevski
           * mailto:nbelaevski@exadel.com
           * created 25.07.2007
           *
           */
          public class TreeModelBean {
           public Boolean adviseNodeOpened(UITree tree) {
           return Boolean.TRUE;
           }
          
           private SimpleRecursiveNode simpleRecursiveNode;
          
           public TreeModelBean() {
           simpleRecursiveNode = new SimpleRecursiveNode(null, null);
           for (int i = 0; i < 5; i++) {
           SimpleRecursiveNode node2 = new SimpleRecursiveNode(simpleRecursiveNode, "Node " + i);
          
           for (int j = 0; j < 6; j++) {
           SimpleRecursiveNode node3 = new SimpleRecursiveNode(node2, "Node " + i + " " + j);
          
           for (int k = 0; k < 4; k++) {
           SimpleRecursiveNode node4 = new SimpleRecursiveNode(node3, "Node " + i + " " + j + " " + k);
           }
           }
           }
           }
          
           public List getSimpleResursiveNodes() {
           return simpleRecursiveNode.getChildren();
           }
          
           int index = 0;
          
           public void add() {
           FacesContext facesContext = FacesContext.getCurrentInstance();
           Loader loader = (Loader) facesContext.getExternalContext().getApplicationMap().get("loaderBean");
          
           Project project = (Project) loader.getProjects().get(1);
          
           Directory directory = (Directory) project.getDirs().get(0);
           Directory directory2 = (Directory) ((Map.Entry) directory.getDirectories().entrySet().iterator().next()).getValue();
          
           File file = new File();
           file.setName(index++ + ":" + UUID.randomUUID().toString());
          
           directory2.addFile(file);
          
           System.out.println(directory2);
           }
          }
          - I've taken bean from http://anonsvn.jboss.org/repos/richfaces/trunk/samples/treeModelDemo

          That works ok for me. Btw, alike problem has been described here: http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4141728#4141728

          Could you please create a runnable WAR and attach it to new issue in JIRA or send it directly to me: nbelaevski at exadel dot com ? Thank you in advance!

          • 2. Re: rich:tree reRender of tree does not repopulate tree
            Mark LoSacco Newbie

            Nick,

            Thanks for your reply - I was able to track down my problem as a result of seeing your example. The problem was in my code and had nothing to do with richfaces.

            -Mark