The next example will show how to make and use a rich:tree
component in an effective way.
First let's create the /view/examples/tree/treeExample.xhtml
page, it might look like this:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <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:rich="http://richfaces.org/rich" template="/layout/template.xhtml"> <ui:define name="body"> <h:form> <rich:tree switchType="ajax" value="#{contactsTree}" var="item"> <rich:treeNode iconLeaf="/img/contact.png" icon="/img/files.png"> <h:outputText value="#{item.name}"/> </rich:treeNode> </rich:tree> </h:form> </ui:define> </ui:composition>
Here, we've defined a tree that gets the data model from the contactsTree
variable and uses Ajax to render the changes (switchType="ajax"
) during the user interaction.
Inside the tree, we've also defined what the standard tree node will look like.
Let's use the backing bean now create a book.richfaces.advcm.modules.main.examples.tree
package, and inside it, a Java class called TreeExampleHelper
.
This class might look like the following code:
package book.richfaces.advcm.modules.main.examples.tree; @Name("treeExampleHelper") @Scope(ScopeType.CONVERSATION) public class TreeExampleHelper { @In(create = true) EntityManager entityManager; @In FacesMessages facesMessages; @In(create = true) GroupsListHelper groupsListHelper; @In(create = true) HomeContactsListHelper homeContactsListHelper; @Factory(value = "contactsTree", autoCreate = true, scope = ScopeType.CONVERSATION) public TreeNode fillInContactsTree() { TreeNode tree = new TreeNodeImpl(); for (ContactGroup group : groupsListHelper.getGroups()) { TreeNode groupNode = new TreeNodeImpl(); // Add the sub level // I want only the contacts inside the current // group homeContactsListHelper.setGroupFilter(group); // Force the reloading of the list with the new // filter homeContactsListHelper.sand so onontactsList(null); for (Contact contact : homeContactsListHelper.gand so onontactsList()) { TreeNode contactNode = new TreeNodeImpl(); // Add the contact inside the group contactNode.setData(contact); groupNode.addChild(group.getId() + "_" + contact.getId(), contactNode); } // Add the group with contacts inside groupNode.setData(group); tree.addChild(group.getId(), groupNode); } // Reset the filter homeContactsListHelper.setGroupFilter(null); homeContactsListHelper.sand so onontactsList(null); return tree; } }
The fillInContactsTree()
method is the factory of contactsTree
variable that contains the tree data model (an implementation of the TreeNode
interface). Our tree will contain the Groups/Contacts structure read from the database, and would look like the next screenshot:
A feature we would like to add is state saving this way, we can put the current tree state into a property and keep it between the requests, or store and then reset in another moment (for example, when the user comes back).
In order to achieve that, we have just to add the DataComponentState
property (with getter and setter) inside our bean:
private DataComponentState dataState; public DataComponentState getDataState() { return dataState; } public void setDataState(DataComponentState dataState) { this.dataState = dataState; }
Then we set the componentState
attribute of the rich:tree
component in the XHTML file:
<rich:tree ... componentState="#{treeExampleHelper.dataState}"
We can define some listener to control user interaction with the tree.
The first one we are going to define is the changeExpandListener
, let's add the following method into our bean:
public void changeExpandListener(NodeExpandedEvent event) { action listeners, richtree component:changeExpandListenerUITree tree = (UITree) event.gand so onomponent(); facesMessages.add(StatusMessage.Severity.INFO, "Node changed/expanded: "+trefor exampleetRowData()); }
Notice how we get the UITree
instance from the event passed to the method.
In a seam-gen generated EAR project, in order to have UITree tree = (UITree) event.gand so onomponent()
; working, we have to move all of our libraries to the EAR lib
directory. Refer to the binding paragraph to see how to do that.
Now let's set the rich:tree changeExpandListener
attribute:
<rich:tree ... changeExpandListener="#{treeExampleHelper.changeExpandListener}" ... >
Done! Now we can act when a user expands or closes a part of the tree.
Another useful listener we can set is the nodeSelectListened
. It can be added the same way as the other listener. Let's add the following method into the bean:
public void selectionListener(NodeSelectedEvent event) { UITree tree = (UITree) event.getComponent(); Object selectedObject = tree.getRowData(); if (selectedObject instanceof ContactGroup) { facesMessages.add(StatusMessage.Severity.INFO, "Group selected: "+ ((ContactGroup)selectedObject).getName()); } else { facesMessages.add(StatusMessage.Severity.INFO, "Contact selected: "+ ((Contact)selectedObject).getName()+" "+((Contact)selectedObject).getSurname()); } }
And also add it to the XHTML file:
<rich:tree ... nodeSelectListener="#{treeExampleHelper.selectionListener}" ajaxSubmitSelection="true" ... >
We have also set the ajaxSubmitSelection
attribute to true
in order to "Ajaxize" every listener submission.
You can see the result of selecting a group in the following screenshot:
3.129.26.185