Uploaded image for project: 'RichFaces'
  1. RichFaces
  2. RF-13819

Rich:tree (recursive) selectionChangeListener not invoked

    Details

    • Type: Bug
    • Status: Resolved (View Workflow)
    • Priority: Major
    • Resolution: Duplicate Issue
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      Hi guys,

      My function never get called with a recursive tree. Also, the attribute "selectionChangeListener" documentation is not up to date.

      Doc : "MethodExpression representing an tree node toggle listener method that will be notified when the tree node is
      toggled. The expression must evaluate to a public method that takes an TreeToggleEvent parameter, with a
      return type of void, or to a public method that takes no arguments with a return type of void. In the latter case,
      the method has no way of easily knowing where the event came from, but this can be useful in cases where a
      notification is needed that "some action happened"."

      I add a test case.:

      Tree.xhtml
      <f:view xmlns="http://www.w3.org/1999/xhtml"
      	xmlns:h="http://java.sun.com/jsf/html"
      	xmlns:f="http://java.sun.com/jsf/core"
      	xmlns:rich="http://richfaces.org/rich"
      	xmlns:a4j="http://richfaces.org/a4j"
      	xmlns:ui="http://java.sun.com/jsf/facelets">
      
      	<ui:decorate template="/WEB-INF/templates/publicTemplate.xhtml">
      		<ui:define name="body">
      			<h:form>
      				<rich:tree id="entryTree" var="noeud" selectionType="ajax"
      					selectionChangeListener="#{treeBean.selectionChangeListener}"
      					toggleListener="#{treeBean.toggleNodeListener}">
      					<rich:treeModelRecursiveAdaptor roots="#{treeBean.tree}"
      						nodes="#{noeud.children}" leaf="#{noeud.leaf}">
      						<rich:treeNode expanded="#{noeud.open}">
      							<h:outputText value="#{noeud.value}" />
      						</rich:treeNode>
      					</rich:treeModelRecursiveAdaptor>
      				</rich:tree>
      			</h:form>
      		</ui:define>
      	</ui:decorate>
      </f:view>
      
      TreeBean.java
      /**
       * 
       */
      package tree;
      
      import java.util.ArrayList;
      import java.util.List;
      
      import javax.annotation.PostConstruct;
      import javax.faces.bean.ManagedBean;
      import javax.faces.bean.ViewScoped;
      
      import org.richfaces.component.UITree;
      import org.richfaces.event.TreeSelectionChangeEvent;
      import org.richfaces.event.TreeToggleEvent;
      
      /**
       * Bean.
       * 
       * @author Jonathan Laterreur
       * 
       */
      @ManagedBean
      @ViewScoped
      public class TreeBean implements java.io.Serializable {
      	private static final long serialVersionUID = 5796918620216656166L;
      
      	/**
      	 * Tree
      	 */
      	private List<ValueTreeNode<String>> tree = new ArrayList<ValueTreeNode<String>>();
      
      	public List<ValueTreeNode<String>> getTree() {
      		return tree;
      	}
      
      	public void setTree(List<ValueTreeNode<String>> tree) {
      		this.tree = tree;
      	}
      
      	/**
      	 * Construct tree.
      	 */
      	@PostConstruct
      	public void init() {
      		majTree();
      	}
      
      	/**
      	 * On met a jour l'arbre.
      	 * 
      	 * @throws ServiceException
      	 */
      	private void majTree() {
      		ValueTreeNode<String> root;
      		ValueTreeNode<String> node;
      		ValueTreeNode<String> child;
      
      		root = new ValueTreeNode<String>("root", false);
      		for (int i = 0; i < 10; i++) {
      			node = new ValueTreeNode<String>("n" + i, false);
      			root.addChild("n" + i, node);
      			for (int j = 0; j < 10; j++) {
      				child = new ValueTreeNode<String>("c" + j, true);
      				node.addChild("c" + j, child);
      			}
      		}
      
      		tree.clear();
      		tree.add(root);
      	}
      
      	/**
      	 * Lorsqu'on rouvre ou ferme une node.
      	 * 
      	 * @param event
      	 *            event
      	 */
      	@SuppressWarnings("unchecked")
      	public void toggleNodeListener(TreeToggleEvent event) {
      		UITree treeAbitibi;
      		ValueTreeNode<String> node;
      
      		treeAbitibi = (UITree) event.getSource();
      		node = (ValueTreeNode<String>) treeAbitibi.getRowData();
      		node.setOpen(event.isExpanded());
      	}
      
      	/**
      	 * Test selection
      	 * 
      	 * @param event
      	 */
      	public void selectionChangeListener(TreeSelectionChangeEvent event) {
      		System.out.println("IN");
      	}
      }
      
      publicTemplate.xhtml
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
      	xmlns:h="http://java.sun.com/jsf/html"
      	xmlns:f="http://java.sun.com/jsf/core"
      	xmlns:ui="http://java.sun.com/jsf/facelets">
      
      <h:head>
      	<title><h:outputText value="Test RichFaces" /></title>
      	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      </h:head>
      
      <h:body>
      	<ui:insert name="body" />
      </h:body>
      </html>
      
      ValueTreeNode.java
      package tree;
      
      import java.io.Serializable;
      import java.util.ArrayList;
      import java.util.Iterator;
      import java.util.LinkedHashMap;
      import java.util.List;
      import java.util.Map;
      
      import org.richfaces.model.TreeNode;
      
      import com.google.common.collect.Iterators;
      
      /**
       * Pour l'arbre de richfaces.
       * 
       * @author Jonathan Laterreur
       */
      public class ValueTreeNode<T> implements TreeNode, Serializable {
      	private static final long serialVersionUID = -6035917173189518235L;
      	private T value;
      	private ValueTreeNode<T> parent;
      	private List<Object> keysList = new ArrayList<Object>();
      	private Map<Object, TreeNode> children = new LinkedHashMap<Object, TreeNode>();
      	private boolean leaf;
      	private boolean initialized;
      	private boolean open;
      
      	public ValueTreeNode() {
      		this(false);
      	}
      
      	public ValueTreeNode(boolean leaf) {
      		super();
      		this.leaf = leaf;
      	}
      
      	public ValueTreeNode(T value, boolean leaf) {
      		this(leaf);
      		this.value = value;
      	}
      
      	public ValueTreeNode(T value, boolean leaf, boolean initialized) {
      		this(value, leaf);
      		this.initialized = initialized;
      	}
      
      	public void setParent(ValueTreeNode<T> parent) {
      		this.parent = parent;
      	}
      
      	public ValueTreeNode<T> getParent() {
      		return parent;
      	}
      
      	public T getValue() {
      		return value;
      	}
      
      	public void setValue(T value) {
      		this.value = value;
      	}
      
      	public void clearChildren() {
      		keysList.clear();
      		children.clear();
      	}
      
      	public boolean hasChild() {
      		return !children.isEmpty();
      	}
      
      	public Map<Object, TreeNode> getChildren() {
      		return children;
      	}
      
      	public void setChildren(Map<Object, TreeNode> children) {
      		this.children = children;
      	}
      
      	@SuppressWarnings("unchecked")
      	public void addChild(Object key, TreeNode child) {
      		((ValueTreeNode<T>) child).setParent(this);
      		keysList.add(key);
      		children.put(key, child);
      	}
      
      	@SuppressWarnings("unchecked")
      	public void insertChild(int idx, Object key, TreeNode child) {
      		((ValueTreeNode<T>) child).setParent(this);
      		keysList.add(idx, key);
      		children.put(key, child);
      	}
      
      	@SuppressWarnings("unchecked")
      	public void removeChild(Object key) {
      		TreeNode child;
      
      		child = (TreeNode) getChild(key);
      		if (child instanceof ValueTreeNode)
      			((ValueTreeNode<T>) child).setParent(null);
      
      		children.remove(key);
      		keysList.remove(key);
      	}
      
      	public TreeNode getChild(Object key) {
      		return children.get(key);
      	}
      
      	public Iterator<Object> getChildrenKeysIterator() {
      		return Iterators.unmodifiableIterator(keysList.iterator());
      	}
      
      	public int indexOf(Object key) {
      		return keysList.indexOf(key);
      	}
      
      	public boolean isLeaf() {
      		return leaf;
      	}
      
      	public void setLeaf(boolean leaf) {
      		this.leaf = leaf;
      	}
      
      	public boolean isInitialized() {
      		return initialized;
      	}
      
      	public void setInitialized(boolean initialized) {
      		this.initialized = initialized;
      	}
      
      	public boolean isOpen() {
      		return open;
      	}
      
      	public void setOpen(boolean open) {
      		this.open = open;
      	}
      
      }
      

      Thank you.

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  Unassigned
                  Reporter:
                  jonleyo Jonathan Laterreur
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  3 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: