rich:tree Ever wanted to know if the node you click is a lea
tomzi Jul 13, 2007 5:18 AMI wanted to create a rich:modalPanel containing a rich:tree. When I click on a leaf it should close the panel and update the product in an h:outputText field.
Right now just found out how to make the modalPanel close when I click on a leaf (Product), so I am pretty excited. However, when I click on a node (Product Categorie) it should not close the panel.
This is how I did it:
The magic is following line:
if (!event['treeItem'].hasChilds()) { Richfaces.hideModalPanel('webacform3:panel3') }It tells you nowhere in the rich:tree docu how to find out on the client side if you clicked on a leaf or not. So by debugging with FireBug on Firefox I found the .hasChilds method (which should actually be called hasChildren, but here we go).
The rest of the code is here:
The css (working, adding a scrollbar when the tree extends the modalpanels fixed size):
<style type="text/css">
.dr-mpnl-pnl {overflow:auto!important}
.rich-mpnl-body { height: 92%; width:99%; padding:0px; }
.rich-mpnl-body .content { padding: 10px; }
</style>
The rich:modalpanel containing the rich:tree.
<a4j:form id="webacform3">
<a4j:outputPanel ajaxRendered="true">
<webac:messages />
</a4j:outputPanel>
<a href="javascript:Richfaces.showModalPanel('webacform3:panel3')">
<h:outputText id="currentlySelectedProduct"
value="#{chooseActivation_backing.productTypes.selectedProduct == null ?
'Select Product' :
chooseActivation_backing.productTypes.selectedProduct.name}"></h:outputText>
</a>
<rich:modalPanel id="panel3"
resizeable="false" moveable="false" height="300"
width="400">
<f:facet name="header">
<h:outputText value="Select Product"></h:outputText>
</f:facet>
<f:facet name="controls">
<a
href="javascript:Richfaces.hideModalPanel('webacform3:panel3')">X</a>
</f:facet>
<div class="content" >Please Select a Product: <br />
<rich:tree id="tree" switchType="client"
value="#{chooseActivation_backing.productTypes.currentProducts}"
var="data" ajaxSubmitSelection="true"
reRender="currentlySelectedProduct"
onselected="if (!event['treeItem'].hasChilds()) { Richfaces.hideModalPanel('webacform3:panel3') }"
preserveModel="none"
nodeFace="#{!empty data.subProducts == true ? 'input' : 'text'}"
immediate="false"
nodeSelectListener="#{chooseActivation_backing.productTypes.onTreeSelect}">
<rich:treeNode type="input"
oncollapse="Element.removeClassName(event['treeItem'].getElement(), 'colored')"
onexpand="Element.addClassName(event['treeItem'].getElement(), 'colored')">
<h:outputText value="#{data.name}" />
</rich:treeNode>
<rich:treeNode type="text" nodeClass="customNode">
<h:commandLink value="#{data.name}" />
</rich:treeNode>
</rich:tree></div>
</rich:modalPanel>
</a4j:form>
And the ProductsDto class which is referenced in the backingbean chooseActivation_backing
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.event.FacesEvent;
import org.richfaces.component.TreeNode;
import org.richfaces.component.UITree;
import org.richfaces.component.UITreeNode;
import org.richfaces.component.events.NodeSelectedEvent;
import com.bearingpoint.ta.product.add.jsf.TreeNodeBuilder;
import com.bearingpoint.ta.product.add.model.ConcreteProductBuilder;
import com.bearingpoint.ta.product.add.model.Product;
import com.bearingpoint.ta.product.add.model.ProductBuilder;
public class ProductsDto {
private TreeNode currentProducts;
private List<Product> productHirarchie;
private TreeNode selectedNode = null;
public void init()
{
createProductTreeComponent();
}
private UITree getTree(FacesEvent event) {
UIComponent component = event.getComponent();
if (component instanceof UITree) {
return ((UITree) component);
}
if (component instanceof UITreeNode) {
return ((UITree) component.getParent());
}
return null;
}
public void onTreeSelect(NodeSelectedEvent event) {
if (getTree(event).getTreeNode()!=null && getTree(event).isLeaf()) {
this.selectedNode = getTree(event).getTreeNode();
}
}
private void createProductTreeComponent() {
currentProducts = new TreeNodeBuilder(productHirarchie).build();
}
public static ProductBuilder createNewProducts() {
return ConcreteProductBuilder.newProducts();
}
public void setProductHirarchie(List<Product> productHirarchie) {
this.productHirarchie = productHirarchie;
}
public List<Product> getProductHirarchie() {
return productHirarchie;
}
public void setCurrentProducts(TreeNode currentProducts) {
this.currentProducts = currentProducts;
}
public TreeNode getCurrentProducts() {
return currentProducts;
}
public Product getSelectedProduct() {
return getSelectedNode() == null ? (Product) null : ((Product) getSelectedNode().getData());
}
public TreeNode getSelectedNode() {
return selectedNode;
}
}onTreeSelect is called whenever a node in the rich:tree has been selected. This method stores the currently selected node (selectedNode) only if it is a leaf (=Product)
createProductTreeComponent() only creates a TreeNode tree out of a Product tree, where each node in the TreeNode references to the Product instance (TreeNode.setData()). So the elements referenced via var="data" is actually a Product instance.
Note that the outputText field also references the selectedNode, so when you selected a leaf, the modalPanel closes and the outputField is being updated.
I worked quite a while on this - and I just wanted to share my outcome :) Have fun