4 Replies Latest reply on Dec 29, 2010 5:55 AM by Nick Belaevski

    Tree with checkbox, onclick rerender page, save state?

    ziqi zhang Newbie

      Hi, I am new to JSF and RichFaces, I have played with the tree demos and made my first step towards my own custom tree, but Im now stuck with using the tree together with selectboolean checkbox. My requirements are:

      1. Put a selectboolean checkbox next to each tree node
      2. On change each checkbox, save tree state (i.e., remember which nodes are checked, and expanded), reload data, then re-render the tree - because reloading data will reset the tree node labels so I have to re-render the whole tree.

      With following code (but with the lines highlited in red and bold commented out) , I have managed to achieve 1, and most of 2 except that I cannot save the state of checkboxes. Every time the tree gets re-rendered, all checkboxes values are reset. If I added lines marked in red, which adds componentState attributes to the tree, the tree doesnt even work anymore - that is, clicking a node will no longer expand it, and clicking a checkbox will have no response.



      What have I done wrong and how should I achive this please? Any hints much appreciated! Thanks in advance

      <f:view>
       <h:form>
       <h:panelGrid columns="2" width="100%">
      
       <rich:tree id="myTree"
       style="width:300px"
       switchType="ajax"
       componentState="#{treeTest.treeState}" <!--if I delete these two lines the tree works but does not save checkbox states; if I keep these two lines the tree even doesnt work-->
       stateVar="treeState">
       <rich:recursiveTreeNodesAdaptor id="myTreeNodes" roots="#{treeTest.rootChildren}" var="item"
       nodes="#{item.children}">
       <rich:treeNode id="myTreeNode">
       <h:selectBooleanCheckbox id="checkbox" value="#{item.checked}">
       <a4j:support
       event="onclick"
       reRender="myTree"
       action="#{item.processCheckBoxChanged}"
       />
       </h:selectBooleanCheckbox>
       <h:outputText value="#{item.label}"/>
       </rich:treeNode>
       </rich:recursiveTreeNodesAdaptor>
       </rich:tree>
      
       </h:panelGrid>
      
       </h:form>
      </f:view>
      


      The bean
      public class CustomTreeNode {
      
       protected String label;
       protected String id;
       protected boolean checked;
       protected TreeState treeState;
      
       public CustomTreeNode() {
       }
      
       public String getLabel() {
       return label;
       }
      
       public void setLabel(final String label) {
       this.label = label;
       }
      
       public String getId(){
       return id;
       }
       public void setId(final String id){
       this.id=id;
       }
      
       public boolean isChecked() {
       return checked;
       }
      
       public void setChecked(final boolean checked) {
       this.checked = checked;
       }
       public TreeState getTreeState(){
       return treeState;
       }
       public void setTreeState(final TreeState state){
       treeState=state;
       }
      
       public CustomTreeNode[] getChildren() {
       List<CustomTreeNode> rs = new ArrayList<CustomTreeNode>();
       for (int i = 0; i < 10; i++) {
       CustomTreeNode n = new CustomTreeNode();
       n.setLabel("n Label " + Math.random());
       n.setId("id="+i);
       n.setChecked(false);
       rs.add(n);
       }
       return rs.toArray(new CustomTreeNode[0]);
       }
      
       public CustomTreeNode[] getRootChildren() {
       //read from database
       List<CustomTreeNode> rs = new ArrayList<CustomTreeNode>();
       for (int i = 0; i < 3; i++) {
       CustomTreeNode n = new CustomTreeNode();
       n.setLabel("Test label "+Math.random());
       n.setId("id="+i);
       n.setChecked(true);
       rs.add(n);
       }
       return rs.toArray(new CustomTreeNode[0]);
       }
      
       public void processCheckBoxChanged(){
       checked=!checked;
       System.out.println("This NODE "+id+" with "+label+" is "+checked);
       }