1 2 Previous Next 23 Replies Latest reply on Sep 22, 2008 9:40 AM by nbelaevski

    Tree component with multiple select

    ykravchenko

      Hi, all
      Is it possible to implement tree component with multiple selects. May be some sort of 'Check box tree views' ?

      Best regards.[/img]

        • 1. Re: Tree component with multiple select
          ykravchenko

          Hey. Doesn't anyone know an answer to this question? What's wrong with you guy at least give a clue or something... I really need and appreciate your help

          Regards Yevgen Kravchenko

          • 2. Re: Tree component with multiple select
            viggo.navarsete

            Hi ykravchenko!

            "What's wrong with you guy at least give a clue or something... I really need and appreciate your help "..please be more polite when asking questions on forums like this. If you took the time to search for an existing solution/thread on the subject on this forum I'm sure you would find information about it.
            When it comes to your actual problem, I know that I have posted several times about what you're looking for.

            • 3. Re: Tree component with multiple select
              viggo.navarsete

              If you look at my comments in this thread, it should get you started: http://jboss.com/index.html?module=bb&op=viewtopic&t=113635&postdays=0&postorder=asc&start=20

              • 4. Re: Tree component with multiple select
                viggo.navarsete

                and please don't hesitate to ask follow-up questions if you need more help. I've got a solution implemented, and will assist you if necessary:)

                • 5. Re: Tree component with multiple select
                  ykravchenko

                  I looked at yours implementation, mine is a little bit different, I don't use checkboxes instead to mark selected node I use css styles.

                  I waht i do is...

                  <rich:tree id="tree" switchType="client"
                   value="#{controller.treeRoot}"
                   nodeSelectListener="#{controller.processNodeSelection}"
                   ajaxSubmitSelection="true" var="node">
                  
                  <rich:treeNode nodeClass="#{node.css}" >
                   <h:outputText value="#{node.name}" />
                  </rich:treeNode>
                  </rich:tree>
                  


                  In backing bean is process selection change:
                  HtmlTree tree = (HtmlTree) event.getSource();
                  Object object = tree.getRowData();
                  
                  getTreeSelectionController().setTree(tree);
                  treeSelectionController.onClick();
                  


                  And finaly my Selection controller should do this:
                  Object data = getTree().getRowData();
                  if (data instanceof ITreeElement) {
                   processSelection((ITreeElement) data);
                  }
                  
                  void processSelection(ITreeElement element) {
                   Validate.notNull(element);
                  
                   if (SELECTED_ALL.equals(element.getSelectionState())) {
                   element.setSelectionState(SELECTED_NONE);
                   } else {
                   element.setSelectionState(SELECTED_ALL);
                   }
                   }
                  

                  Everything would work fine until I try to deselect node that was selected right node, in this case nodeSelectListener wouldn't fire event and it's true because selection hasn't changed....

                  Could anyone please suggest me how to make selection processing event be fired, maybe change selection by means of api?

                  • 6. Re: Tree component with multiple select
                    ykravchenko

                    Great apologizes for my previous post, I'm so exited, because I need this task to be done quickly. viggo.navarsete thank you for quick response. In two words I have the problem that when I try to deselect row that is currently selected nodeSelectListener will not be fired. Please help

                    Best regards Yevgen Kravchenko

                    • 7. Re: Tree component with multiple select
                      viggo.navarsete

                      Good evening ykravchenko:)

                      I'm not sure if I have the complete solution to you, but I think you should look at other ways of telling if a node is selected than using the nodeSelectListener. What about using the adviseNodeSelected?
                      I have seen this method binding used in other threads on this forum, it might help you?!
                      http://jboss.com/index.html?module=bb&op=viewtopic&t=119860
                      http://www.jboss.com/index.html?module=bb&op=viewtopic&t=121405
                      http://jboss.com/index.html?module=bb&op=viewtopic&t=121405

                      Hope it helps...

                      • 8. Re: Tree component with multiple select
                        ykravchenko

                        viggo.navarsete thank You for support, the material that you've provided are helpful indeed.
                        I have already implemented tree with multiple selection, I hope to post the decisions I've made as soon as I have some free time. I'm sure that we should share knowledge so in couple of days there would be a topic on this forum explaining how to achieve multi selection

                        This are my emails: idm@mksat.net
                        Please fill free to contact me. You were the only person who really paid some attention to this post. Thans

                        • 9. Re: Tree component with multiple select
                          viggo.navarsete

                          I'm glad that I could help you, or at least kick you in the right direction ;)
                          I was also kinda frustrated when I first started to use JSF/Richfaces, there were so many options, so many things to get used to, and like you, I also had a very tight schedule to deliver my software. Hopefully we can share knowledge here or by email and that we both get a better understanding of the different Richfaces components :)

                          Have a nice day!!

                          • 10. Re: Tree component with multiple select
                            ykravchenko

                            Hi Viggo

                            Could you provide some more details of your solution implementing tree with multiple selection ability using checkboxes?

                            Regards

                            • 11. Re: Tree component with multiple select
                              viggo.navarsete

                              Sure :)

                              Here is the jsp code fragment which specifies the tree:

                               <r:tree switchType="ajax" value="#{searchBean.searchResultNode.data}" var="item" nodeFace="#{item.type}" selectedClass="selectedNode">
                               <r:treeNode highlightedClass="treeLink" type="organizationNode">
                               <h:selectBooleanCheckbox value="#{item.selected}">
                               <a:support event="onclick" actionListener="#{item.selectDetailsForSummary}" reRender="summaryPanel"/>
                               </h:selectBooleanCheckbox>
                               <a:commandLink styleClass="treeLink" reRender="detailsPanel,tbuPanel" actionListener="#{item.lookupDetails}" value="#{item.organizationName}"/>
                               </r:treeNode>
                               <r:treeNode highlightedClass="treeLink" type="entityNode">
                               <h:selectBooleanCheckbox value="#{item.selected}">
                               <a:support event="onclick" actionListener="#{item.selectDetailsForSummary}" reRender="summaryPanel"/>
                               </h:selectBooleanCheckbox>
                               <a:commandLink styleClass="treeLink" reRender="detailsPanel,tbuPanel" actionListener="#{item.lookupDetails}" value="#{item.entityId}"/>
                               </r:treeNode>
                               </r:tree>
                              


                              To feed the tree with data I have implemented several classes which implements the TreeNode interface. First of all I have created a SearchResultNode which returns data for the "root level" of the tree, which basically is all the organizations. Then I created an OrganizationNode class (also implementing the TreeNode interface) which gives back data when expanding the organization node, which is all the entities belonging to an organization.

                              This is the SearchResultNode implementation:

                              public class SearchResultNode implements TreeNode {
                              
                               private Map organizations; // Organizations
                               private Object state1; // TODO: do we need it? Taken from a sample application
                               private Object state2; // TODO: do we need it? Taken from a sample application
                               private boolean selected = false; // checkbox
                              
                               private Map getOrganizations() {
                               if (this.organizations == null) {
                               organizations = new HashMap();
                               }
                               return this.organizations;
                               }
                              
                               public void addOrganization(OrganizationNode organization) {
                               addChild(Long.toString(organization.getId()), organization);
                               organization.setParent(this);
                               }
                              
                               public Object getData() {
                               return this;
                               }
                              
                               public void setData(Object arg0) {
                               // TODO: ??
                               }
                              
                               public boolean isLeaf() {
                               return getOrganizations().isEmpty();
                               }
                              
                               public Iterator getChildren() {
                               return getOrganizations().entrySet().iterator();
                               }
                              
                               public TreeNode getChild(Object id) {
                               return (TreeNode) getOrganizations().get(id);
                               }
                              
                               public void addChild(Object identifier, TreeNode child) {
                               getOrganizations().put(identifier, child);
                               }
                              
                               public void removeChild(Object id) {
                               getOrganizations().remove(id);
                               }
                              
                               public TreeNode getParent() {
                               return null; // this is root node
                               }
                              
                               public void setParent(TreeNode arg0) {
                               }
                              
                               public Object getState1() {
                               return state1;
                               }
                              
                               public void setState1(Object state1) {
                               this.state1 = state1;
                               }
                              
                               public Object getState2() {
                               return state2;
                               }
                              
                               public void setState2(Object state2) {
                               this.state2 = state2;
                               }
                              
                               // this is what you specify in you jsp on the attribute type for the r:treeNode element
                               public String getType() {
                               return "searchResultNode";
                               }
                              
                               public boolean isSelected() {
                               return selected;
                               }
                              
                               public void setSelected(boolean selected) {
                               this.selected = selected;
                               }
                              }


                              Then the OrganizationNode implementation:
                              public class OrganizationNode implements TreeNode {
                              
                               private long id;
                               private String organizationName;
                               private Map entities = new HashMap(); // children
                               private TreeNode parent; // parent
                               private boolean selected = false; // checkbox
                              
                               public OrganizationNode(long id) {
                               this.id = id;
                               }
                              
                               public String getOrganizationName() {
                               return organizationName;
                               }
                              
                               public void setOrganizationName(String organizationName) {
                               this.organizationName = organizationName;
                               }
                              
                               public void addEntity(EntityNode entity) {
                               addChild(Long.toString(entity.getId()), entity);
                               entity.setParent(this);
                               }
                              
                               public Object getData() {
                               return this;
                               }
                              
                               public void setData(Object arg0) {
                               }
                              
                               public boolean isLeaf() {
                               return entities.isEmpty();
                               }
                              
                               public Iterator getChildren() {
                               return entities.entrySet().iterator();
                               }
                              
                               public TreeNode getChild(Object id) {
                               return (TreeNode) entities.get(id);
                               }
                              
                               public void addChild(Object identifier, TreeNode child) {
                               entities.put(identifier, child);
                               }
                              
                               public void removeChild(Object id) {
                               entities.remove(id);
                               }
                              
                               public TreeNode getParent() {
                               return this.parent;
                               }
                              
                               public void setParent(TreeNode parent) {
                               this.parent = (SearchResultNode) parent;
                               }
                              
                               // this is what you specify in you jsp on the attribute type for the r:treeNode element
                               public String getType() {
                               return "organizationNode";
                               }
                              
                               public long getId() {
                               return id;
                               }
                              
                               public void setId(long id) {
                               this.id = id;
                               }
                              
                               public boolean isSelected() {
                               return selected;
                               }
                              
                               public void setSelected(boolean selected) {
                               this.selected = selected;
                               }
                              
                               public void lookupDetails(ActionEvent event) {
                               // not important to get the tree up and running, but an event triggered when clicking on the node, which also rerenders some other panels on the page. You can skip this, or implement it if you want, but then you have to carefully look at the jsp to see which elements are rerendered.
                               }
                              
                               public void selectDetailsForSummary(ActionEvent event) {
                               // not really important to get the tree up and running, but an event I've used to build up a summary of all nodes selected. It's triggered when selecting/unselecting a checkbox.
                               }
                              }
                              


                              Then the EntityNode implementation:
                              public class EntityNode implements TreeNode {
                              
                               private long id;
                               private String entityId;
                               private OrganizationNode parent; // parent
                               private boolean selected = false; // checkbox
                              
                               public EntityNode(long id) {
                               this.id = id;
                               }
                              
                               public Object getData() {
                               return this;
                               }
                              
                               public void setData(Object arg0) {
                               }
                              
                               public boolean isLeaf() {
                               return true; // TODO: doesn't have any more levels yet.
                               }
                              
                               public Iterator getChildren() {
                               // TODO: Fix me!
                               return new ArrayList().iterator(); // work around limitation for TreeNode
                               }
                              
                               public TreeNode getChild(Object id) {
                               throw new UnsupportedOperationException("Entity does not have children");
                               }
                              
                               public void addChild(Object id, TreeNode child) {
                               throw new UnsupportedOperationException("Entity does not have children");
                               }
                              
                               public void removeChild(Object id) {
                               throw new UnsupportedOperationException("Entity does not have children");
                               }
                              
                               public TreeNode getParent() {
                               return this.parent;
                               }
                              
                               public void setParent(TreeNode parent) {
                               this.parent = (OrganizationNode) parent;
                               }
                              
                               // this is what you specify in you jsp on the attribute type for the r:treeNode element
                               public String getType() {
                               return "entityNode";
                               }
                              
                               public String getEntityId() {
                               return entityId;
                               }
                              
                               public void setEntityId(String entityId) {
                               this.entityId = entityId;
                               }
                              
                               public long getId() {
                               return id;
                               }
                              
                               public void setId(long id) {
                               this.id = id;
                               }
                              
                               public boolean isSelected() {
                               return selected;
                               }
                              
                               public void setSelected(boolean selected) {
                               this.selected = selected;
                               }
                              
                               /**
                               * Method for looking up Entity details
                               */
                               public void lookupDetails(ActionEvent event) {
                               // nothing important to get the tree up and running, but a way to get details when the entity node is clicked. As you can see from the jsp, it will also rerender some other panels on the page.
                               }
                              
                               public void selectDetailsForSummary(ActionEvent event) {
                               // not really important to get the tree up and running, but an event I've used to build up
                              a summary of all nodes selected. It's triggered when selecting/unselecting a checkbox.
                               }
                              }
                              


                              If you get any compile errors, it's just because I've tried to copy and paste as much as possible without revealing anything confidential. So, please give feedback if it doesn't compile. Also, I implemented this tree before the TreeAdapter and Recursive TreeAdapter were available. I'm not sure if it can be done easier with those classes, but I'm at least able to make it work the way I do:)

                              Good luck to you :)

                              • 12. Re: Tree component with multiple select
                                viggo.navarsete

                                and to trigger the population of data in the tree I have a button on the jsp page which triggers a search, a method in my backing bean. When the search has returned data I have another private method actually filling the data structure:

                                jsp:

                                <h:commandButton action="#{searchBean.search}" value="Search"/>
                                


                                backing bean:
                                
                                 private SearchResultNode searchResultNode;
                                
                                 public SearchResultNode getSearchResultNode() {
                                 return searchResultNode;
                                 }
                                
                                 public void setSearchResultNode(SearchResultNode searchResultNode) {
                                 this.searchResultNode = searchResultNode;
                                 }
                                
                                 public String search() {
                                 // TODO: do some logic to retrieve data from somewhere(database/webservice/whatever)
                                
                                 populateSearchResultNode(/* TODO: add a datastructure returned from search*/)
                                 }
                                
                                 private void populateSearchResultNode( /* TODO: add a datastructure returned from search */) {
                                 searchResultNode = new SearchResultNode(); // creates the root level TreeNode
                                 long id = 0; // used to generate id's for each unique node in the tree, important to have this.
                                
                                 /*
                                 * iterate over the datastructure from the search, which would be input to this method and add data to the tree.
                                 * As an example, I just randomly generate some organizations and append some entities to it. In real life, you
                                 * would probably just add the organizations to this list, and then fetch the entities when you expand the
                                 * organization node!
                                 */
                                 for( int i = 0; i < 30; i++ ) {
                                 OrganizationNode organization = new OrganizationNode( id++ ); // each node needs an unique id!!
                                 organization.setOrganizationName( "Name-" + i );
                                 for( int j = 0; j < 10; j++ ) {
                                 EntityNode entityNode = new EntityNode( id++ ); // each node needs an unique id!!
                                 entityNode.setEntityId( "id-" + j );
                                 organization.addEntity( entityNode ); // adds the entity to the organization
                                 }
                                 searchResultNode.addOrganization( organization ); // adds the organization to the searchresult
                                 }
                                 }
                                }
                                


                                • 13. Re: Tree component with multiple select
                                  ykravchenko

                                  HI viggo.navarsete

                                  Thank You for quick response, what I'm trying to do right now is something like this http://www.zapatec.com/website/main/products/prod3/demo.jsp#checkboxes.html

                                  I'd like to be able to select all child nodes (set checkboxes to true) if my parent checkbox is checked.

                                  Have you mastered to achieve that functionality?
                                  Regards Yevgen Kravchenko

                                  • 14. Re: Tree component with multiple select
                                    viggo.navarsete

                                    Hi ykravchenko!
                                    I haven't tried what you ask for, but I _think_ it is as simple as adding more functionality into each setSelected method of the TreeNode implementations. In each SetSelected you have to first set the current node to selected/unselected as you do now, then you have to retrieve all the children (getChildren) which give you an Iterator. You have to iterate through each child and call the setSelected. And if you do so in each TreeNode implementation it will recursively call the setSelected on all children from the node you selected...I think:) But, haven't tried it, so you might give it a shot, and then ask for more help. At least I think the clue here is to recursively call setSelected on all children (and children-children..and so on) until you reach haven't got any leaf's left.

                                    1 2 Previous Next