16
votes

I'm running Primefaces 3.2 and JSF 2.0 on Glassfish 3.

I've tried a lot, to programatically set the selected node from a managed bean. That includes setting the selected node like this:

public void setSelectedTreeNode(String name) {
TreeNode root = treeBean.getRoot();
List<TreeNode> tree = root.getChildren();
for(TreeNode node:tree) {
  if(node.getData().toString().contains(name)) {
    System.out.println("found the node to select");
    treeBean.setSelectedNode(node);
    break;
  }
}
RequestContext context = RequestContext.getCurrentInstance(); 
context.update(":navForm:treeSingle");
}

The "found the node to select" gets printed in the terminal, but the node is not selected in the Tree in the web page..

The tree is like this:

<h:form id="navForm">
<p:tree id="treeSingle" value="#{treeBean.root}" var="node"  
       selectionMode="single" styleClass="treeStyle" 
       selection="#{treeBean.selectedNode}"
       cache="false"
       >  
   <p:ajax event="select" listener="#{treeBean.onNodeSelect}" update=":mainForm" />
   <p:treeNode>  
       <h:outputText value="#{node}" escape="false" />  
   </p:treeNode>  

Edit: TreeBean is built like this:

@ManagedBean
@SessionScoped    
public class TreeBean implements Serializable {  

private TreeNode root;  

private TreeNode selectedNode;  

public TreeBean() {  
    root = new DefaultTreeNode("Root", null);  
    TreeNode node0 = new DefaultTreeNode("Node 0", root);  
    TreeNode node1 = new DefaultTreeNode("Node 1", root);  
    TreeNode node2 = new DefaultTreeNode("Node 2", root);  

    TreeNode node00 = new DefaultTreeNode("Node 0.0", node0);  
    TreeNode node01 = new DefaultTreeNode("Node 0.1", node0);  

    TreeNode node10 = new DefaultTreeNode("Node 1.0", node1);  
    TreeNode node11 = new DefaultTreeNode("Node 1.1", node1);  

    TreeNode node000 = new DefaultTreeNode("Node 0.0.0", node00);  
    TreeNode node001 = new DefaultTreeNode("Node 0.0.1", node00);  
    TreeNode node010 = new DefaultTreeNode("Node 0.1.0", node01);  

    TreeNode node100 = new DefaultTreeNode("Node 1.0.0", node10);  
}  

public TreeNode getRoot() {  
    return root;  
}  

public TreeNode getSelectedNode() {  
    return selectedNode;  
}  

public void setSelectedNode(TreeNode selectedNode) {  
    this.selectedNode = selectedNode;  
}  
}

Does anyone have any idea on how to do this?

7
what does treeBean.setSelectedNode(node) do? Can you show the code of that method?damian
updated the question with TreeBean. It's basically just a plain setter. Built like this: primefaces.org/showcase/ui/treeSelectionSingle.jsfbaron5
ok. the method setSelectedTreeNode is in another bean right? what are the scopes of the beans? are you injecting using ManagedProperty? are you sure that the injected treeBean is the same treeBean that is used by the page? (maybe a new instance is being created)damian
Actually an interesting question. The bean is SessionScoped, but I'm editing an old application that is upgraded from JSF 1.1 to JSF 2.0, hence I'm using the old FacesContext facesContext = FacesContext.getCurrentInstance(); VariableResolver vr = facesContext.getApplication().getVariableResolver(); TreeBean treeBean = (TreeBean) vr.resolveVariable(facesContext, "TreeBean"); instead of injection. Maybe there's something there..baron5
I suggest you debug or add some logging to determine if the same instance is being used. Maybe with your code a new instance is created.. Also you could try to use @ManagedProperty(value="#{treeBean}" instead of the JSF 1.1 codedamian

7 Answers

17
votes

I solved it using:

node.setSelected(true);

I discovered that selecting the node is not enough for the "tree component" to expand from root node to selected node.

For this, I used the following approach. On the view :

 <p:ajax event="expand" listener="#{tree.onExpand}"/>

on the java code:

public void onExpand(NodeExpandEvent event) {
    expand(event.getTreeNode());
}

private void expand(TreeNode treeNode){
    if (treeNode.getParent()!=null){
        treeNode.getParent().setExpanded(true);
        expand(treeNode.getParent());
    }
}
5
votes

for me none of the above worked. because from what I see in the console, the child nodes don't have any ids let alone any row key number so I used jQuery advanced class selector with the help of the rowKey attribute so I had to use

String script = "PF('treeSingleWidget').selectNode($(\"td[data-rowkey='" + selectedNode.getRowKey() + "']\"))";
Primefaces.current().executeScript(script);
3
votes

To highlight selected tree node on client side from backing bean call selectNode() method on tree widget component.

First, set widget var attribute to jsf tree component:

<p:tree id="treeSingle" widgetVar="treeSingleWidget"

Than you can test it from browser console:

PrimeFaces.widgets.treeSingleWidget.selectNode($("#treeSingle\\:1"), true);

First method argument represents node jquery object which was obtained by it`s id(colon symbol must be escaped by two backslashes). If second parameter set to false then node selection event will be fired.

Finally, make javascript call from backing bean:

StringBuilder sb = new StringBuilder();
    sb.append("PrimeFaces.widgets.treeSingleWidget.selectNode(");
    sb.append("$(\"#treeSingle\\\\:");
    sb.append(selectedNode.getRowKey());
    sb.append("\")");
    sb.append(", true)");
    RequestContext.getCurrentInstance().execute(sb.toString());

P.S. to discover component js api type in browser console

PrimeFaces.widget.VerticalTree.prototype
1
votes

In the above if statement, when true, do a node.setSelected(true);

I use that to set nodes on as required. The reverse obviously has the reverse effect; it turns them off. My use case has been a boolean check box to turn all nodes on or off as I have quite a few running down the side of a tree. My actual code, involving a few methods, is therefore:-

public Boolean getSelectionState() {
    return selectionState;
}

public void setSelectionState(Boolean selectionState) {
    this.selectionState = selectionState;
}

public String getSelectLabel() {
    return selectionState ? "De-select all" : "Select all";
}

/**
 * Flips all nodes on or off depending on checkbox.
 */
public void onSelectChange() {
    if (prefs.isDebug()) {
        LOG.log(Level.INFO, "Value change event occured. Selection state is:{0}", selectionState);
    }
    for (TreeNode node : rootNode.getChildren()) {
        node.setSelected(selectionState);
    }
    nodes = new ArrayList(rootNode.getChildren());
    selectedNodes = nodes.toArray(new TreeNode[nodes.size()]);
    mapDevices();
}

I am however, using 3.4 on JSF 2 on GF 3. I don't know if there is a difference.

Regs

Tim

1
votes

please add node.setSelected(true) below treeBean.setSelectedNode(node); and it should work.

0
votes

Tried with primefaces 5.2 and multiselection:

treeBean.setSelectedNode(new TreeNode[]{node});

works.

-1
votes

I'm working with Primefaces 3.0 deployed in Glassfish 3.1 Build 43;

The treeNode was or is selected automaticly with : myTreeNode.setSelected(true);

Example :

 for (TreeNode m2:root.getChildren())   {

         if (((Menu) m2.getData()).getId() != null) {

            if (me.getId().equals(((Menu) m2.getData()).getId())) {

                                            m2.setSelected(true);
                                            break;
                                        }
                                    }
                                }