6 Replies Latest reply on Apr 11, 2008 2:02 PM by Paul Pantages

    Problem with rich:tree with added node edit capability

    George Lezhava Newbie

      I am writing an application using Facelets and RichFaces( currently it's 3.14 but i am planning to move it on 3.20). The idea is to made a tree, populated with vendors, each having nodes with their address information. When user clicks Edit button next to the address node, the values become editable, and instead of Edit button, Save button appears, which when pressed updates address info.
      Here is my code:

      test.xhtml

      <ui:composition xmlns="http://www.w3.org/1999/xhtml"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:f="http://java.sun.com/jsf/core"
       xmlns:a4j="http://richfaces.org/a4j"
       xmlns:rich="http://richfaces.org/rich">
      
       <a4j:form>
       <h:outputText value="aaa" />
       <rich:panel>
       <rich:tree style="width:300px"
       value="#{rootTreeNode.data}" var="item" nodeFace="#{item.type}">
      
       <rich:treeNode type="vendor">
       <h:outputText value="#{item.dataObj.vendorName}" />
       </rich:treeNode>
       <rich:treeNode type="addressRoot">
       <h:outputText value="Addresses" />
       </rich:treeNode>
       <rich:treeNode type="address">
      
       <table>
       <tr>
       <td><a4j:htmlCommandLink value="Edit"
       action="#{item.startEdit}" /></td>
       <td><h:outputText value="#{item.dataObj.address}" /></td>
       <td><h:outputText value="#{item.dataObj.phoneNumber}" /></td>
       </tr>
       </table>
      
       </rich:treeNode>
       <rich:treeNode type="address_edit">
      
       <table>
       <tr>
       <td><a4j:htmlCommandLink value="Save"
       action="#{item.endEdit}" /></td>
       <td><h:inputText value="#{item.dataObj.address}" /></td>
       <td><h:inputText value="#{item.dataObj.phoneNumber}" /></td>
      
       </tr>
       </table>
      
       </rich:treeNode>
      
       </rich:tree>
      
       </rich:panel>
       </a4j:form>
      </ui:composition>
      


      RootTreeNode.java
      public class RootTreeNode implements TreeNode{
      
       private Map<Object,TreeNode> childNodes;
      
       public void addChild(Object arg0, TreeNode arg1) {
       this.getChildNodes().put(arg0, arg1);
       arg1.setParent(this);
      
       }
      
       public TreeNode getChild(Object arg0) {
       // TODO Auto-generated method stub
       return (TreeNode)getChildNodes().get(arg0);
       }
      
       public Iterator getChildren() {
       // TODO Auto-generated method stub
       return getChildNodes().entrySet().iterator();
       }
      
       public Object getData() {
       // TODO Auto-generated method stub
       return this;
       }
      
       public TreeNode getParent() {
       // TODO Auto-generated method stub
       return null;
       }
      
       public boolean isLeaf() {
       // TODO Auto-generated method stub
       return false;
       }
      
       public void removeChild(Object arg0) {
       getChildNodes().remove(arg0);
      
       }
      
       public void setData(Object arg0) {
       // TODO Auto-generated method stub
      
       }
      
       public void setParent(TreeNode arg0) {
       // TODO Auto-generated method stub
      
       }
      
       public Map<Object, TreeNode> getChildNodes() {
       if (childNodes==null)
       initData();
       return childNodes;
       }
      
       private void initData() {
       this.childNodes= new LinkedHashMap<Object, TreeNode>();
      
       InitializationBean bean= AppHelper.getObject("appScope");
       Map vendorsMap= bean.getVendorsMap();
      
       for (Iterator it=vendorsMap.keySet().iterator(); it.hasNext();)
       {
       Object key= it.next();
       Vendor vendor=(Vendor)vendorsMap.get(key);
       TreeNodeImpl<Vendor> vt= new TreeNodeImpl<Vendor>();
      
       TreeNodeImpl<Object> addressesRoot= new TreeNodeImpl<Object>();
       addressesRoot.setType("addressRoot");
       addressesRoot.setLeaf(false);
       addressesRoot.setDataObj(null);
       addressesRoot.setParent(vt);
       vt.getChildNodes().put(1, addressesRoot);
      
      
       for (Iterator it_at=vendor.getAddress().iterator(); it_at.hasNext();)
       {
       Address address= (Address)it_at.next();
       Object addr_key=address.getId();
       TreeNodeImpl<Address> at= new TreeNodeImpl<Address>();
       at.setType("address");
       at.setLeaf(true);
       at.setDataObj(address);
       at.setParent(addressesRoot);
       addressesRoot.getChildNodes().put(addr_key, at);
       }
      
      
      
       vt.setType("vendor");
       vt.setLeaf(false);
       vt.setDataObj(vendor);
       vt.setParent(this);
       childNodes.put(key, vt);
       }
      
       }
      
       public void setChildNodes(Map<Object, TreeNode> childNodes) {
       this.childNodes = childNodes;
       }
      
       public String getType()
       {
       return "root";
       }
      
      }
      


      TreeNodeImpl.java
      public class TreeNodeImpl<E> implements TreeNode{
      
       /**
       *
       */
       private static final long serialVersionUID = 730448288245225451L;
       private TreeNode parent;
       private String type;
       private Map<Object,TreeNode> childNodes;
       private boolean leaf;
       private E dataObj;
       private boolean editMode=false;
      
      
       public boolean isEditMode() {
       return editMode;
       }
      
       public void setEditMode(boolean editMode) {
       this.editMode = editMode;
       if (this.editMode)
       {
       this.setType(this.getType()+"_edit");
       }
       else
       this.setType(this.getType().substring(0, this.getType().length()-5));
       }
      
       public Map<Object, TreeNode> getChildNodes() {
       if (childNodes==null)
       childNodes=new LinkedHashMap<Object, TreeNode>();
       return childNodes;
       }
      
       public void setChildNodes(Map<Object, TreeNode> childNodes) {
       this.childNodes = childNodes;
       }
      
       public E getDataObj() {
       return dataObj;
       }
      
       public void setDataObj(E dataObj) {
       this.dataObj = dataObj;
       }
      
       public void addChild(Object arg0, TreeNode arg1) {
       // TODO Auto-generated method stub
      
       }
      
       public TreeNode getChild(Object arg0) {
       // TODO Auto-generated method stub
       return childNodes.get(arg0);
       }
      
       public Iterator getChildren() {
       // TODO Auto-generated method stub
       return getChildNodes().entrySet().iterator();
       }
      
       public Object getData() {
       // TODO Auto-generated method stub
       return this;
       }
      
       public TreeNode getParent() {
       return parent;
       }
      
       public boolean isLeaf() {
       // TODO Auto-generated method stub
       return leaf;
       }
      
       public void removeChild(Object arg0) {
       // TODO Auto-generated method stub
      
       }
      
       public void setData(Object arg0) {
       // TODO Auto-generated method stub
      
       }
      
       public void setParent(TreeNode arg0) {
       this.parent=arg0;
      
       }
      
       public String getType() {
       return type;
       }
      
       public void setType(String type) {
       this.type = type;
       }
      
       public void setLeaf(boolean leaf) {
       this.leaf = leaf;
       }
       public String startEdit()
       {
       setEditMode(true);
       return "";
       }
       public String endEdit()
       {
       setEditMode(false);
       return "";
       }
      
      }
      


      The problem is that when i set debug point on method TreeNodeImpl.endEdit() - this breakpoint never hits! I even changed event on Save button to call the same method that is called by Edit button, that is startEdit(), but it is also never called. Am i missing something? I really need this to work.

        • 1. Re: Problem with rich:tree with added node edit capability
          George Lezhava Newbie

          No ideas? I can provide additional info if the problem is not clear from the post. Please help!

          • 2. Re: Problem with rich:tree with added node edit capability
            Paul Pantages Novice

            Hello GeorgeSpear,

            this is a bit of a wild guess, but I ran into a similar problem with list shuttle (I had it in a rich:tab) , where it stopped working after it was ajax rendered.... If you refreshed the whole page the problem would fix itself... I had to give up on the ajax rendering & put swtichmode=server in my tabpanel.

            Are you able to refresh the page while in "edit mode" (with the browser refresh button I mean). See if this causes the save link to work. If it does, are you able to give up on ajax and just use a regular command link for "save"?

            • 3. Re: Problem with rich:tree with added node edit capability
              George Lezhava Newbie

              Thanks for reply.

              In both IE and Firefox, when i press browser Refresh, it asks whether i want to resend post data. When i click yes, it reloads the page, once again hitting the breakpoint on the method which turns edit mode ON, and the page loads with the edit mode. Still Save button doesn't work. Unfortunately it is not about giving up AJAX, because i already did. The only reason why i use a4j:htmlCommandLink is because i read somewhere that h:commandLink has some problems when rerendered. This sample does not work with neither h:commandLink, nor a4j:commandLink nor a4j:htmlCommandLink... That looks quite odd to me, because the only little thing i implemented to a standard rich:tree is this commandLink, and after postback it does not work...

              • 4. Re: Problem with rich:tree with added node edit capability
                Paul Pantages Novice

                Hello George, I don't have any great ideas.

                I noticed that you return an empty string "" from your startEdit method. I usually return null JSF outcome when I want to stay on the same page. I did not know you could use "".

                Also, you may try to crank up the logging level and see if there is some error msg when you hit the save. I have a problem with listShuttle (another one) that behaves just like yours: I can't submit the page. No faces error msg or exception is generated, but there is an error buried in the log about some validation error.

                If you had a validation error you could try immediate="true"

                Also try rendered ="#{item.editMode}" and #{not item.editMode} instead of "type=". I was unable to get the latter to work in my tree ( I don't remember exactly what the symptom was, but I gave up on it.)

                I would also try rendering the page with one of the nodes intially in "edit" mode & see if the intiail renderring would make the save button work.

                Good luck.

                • 5. Re: Problem with rich:tree with added node edit capability
                  George Lezhava Newbie

                  Thanks pdpantages.
                  How can i change logging level and where the log files will be stored? There are no errors in server console - it just silently fails.
                  I tried the initial edit mode - it works the same way, i.e. first click on the link works, regardless whether it's edit mode or not, but the second doesn't.
                  I already tried manipulating with rendered instead of type - no effect :(

                  • 6. Re: Problem with rich:tree with added node edit capability
                    Paul Pantages Novice

                    Hi George, wrt the logs, it depends on whether you are using jboss or not, and which version. I am using 4.2.0.GA; for me, everything is in
                    ...server/default/conf/jboss-log4j.xml

                    Dep on your version, this file might be called just "log4j.xml"
                    If you search your filesystem for just log4j.xml you should find it.

                    Look for an entry like this for the log location:

                     <param name="File" value="${jboss.server.log.dir}/../../../../logs/debug.log"/>
                    

                    PdP