Creating a dynamic context menu dependent on the <rich:tree> selection
kwutzke May 3, 2012 7:00 AMHello,
I have a tree on a page to which I'd like to attach a dynamic context menu depending on the name of the node and its type:
{code}<h:form id="tree-form">
<rich:panel header="Sort Tree">
<rich:tree value="#{nodeManager.rootTreeNode}"
var="treeNode"
nodeType="#{treeNode.type}"
toggleType="client"
selectionType="ajax"
selectionChangeListener="#{nodeManager.selectionChanged}"
id="document-tree">
<rich:treeNode type="root" id="root-node">
...
</rich:treeNode>
<rich:treeNode type="chapter" id="chapter-node">
...
</rich:treeNode>
...
</rich:tree>
<rich:contextMenu target="document-tree" mode="ajax">
<rich:menuItem label="Add chapter to #{nodeManager.selectedNode.name}..." />
<rich:menuItem label="Remove #{nodeManager.selectedNode.name}..."
rendered="#{nodeManager.selectedNodeClassName eq 'ChapterNode'}" />
</rich:contextMenu>
</rich:panel>
</h:form>{code}
NodeManager is a view-scoped bean, which successfully receives the selection changes when the node is left- or right-clicked. It also overwrites the selected node in that bean from which getSelectedNode() returns the instance and getSelectedNodeClassName() returns the simple class name, here "RootNode" or "ChapterNode".
What I want now is a dynamic context menu: roots cannot be deleted (no REMOVE shown), new chapters can only be added to roots or chapters (ADD always shown).
RootNode shall show menu:
* Add chapter to [node name]...
ChapterNode shall show menu:
* Add chapter to [node name]...
* Remove [node name]...
Here's the relevant NodeManager code:
{code}public void selectionChanged(TreeSelectionChangeEvent event)
{
log.info("Tree selection!");
List<Object> selection = new ArrayList<Object>(event.getNewSelection());
Object currentSelectionKey = selection.get(0);
UITree tree = (UITree)event.getSource();
Object storedKey = tree.getRowKey();
tree.setRowKey(currentSelectionKey);
selectedContainerTreeNode = (ContainerTreeNode)tree.getRowData();
tree.setRowKey(storedKey);
log.info("Selected node = " + selectedContainerTreeNode.getName());
}
public Node getSelectedNode()
{
return selectedContainerTreeNode != null ? selectedContainerTreeNode.getNode() : null;
}
public String getSelectedNodeClassName()
{
String className = selectedContainerTreeNode != null ? selectedContainerTreeNode.getNode().getClass().getSimpleName() : null;
log.info("Selected node class name = " + className);
return className;
}{code}
However, the dynamically set selected node and its class name returned are always null, as #{nodeManager.selectedNode.name} renders nothing (empty string?) and the rendered="#{nodeManager.selectedNodeClassName eq 'ChapterNode'}" *always* seems to evaluate to false, even though the selectionChanged listener clearly prints to the console that a new tree node has successfully been set:
{code}12:27:20,662 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node class name = null
12:27:26,082 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node class name = null
12:27:26,083 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Tree selection!
12:27:26,083 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node = wwwwwwwwww
12:27:26,145 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node class name = RootNode
12:27:26,177 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node class name = RootNode
12:27:26,307 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node class name = RootNode
12:27:27,368 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node class name = RootNode
12:27:27,369 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Tree selection!
12:27:27,369 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node = subb
12:27:27,427 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node class name = ChapterNode
12:27:27,463 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node class name = ChapterNode
12:27:27,581 INFO [com.company.project.facade.NodeManager] (http-localhost-127.0.0.1-8080-3) Selected node class name = ChapterNode{code}
What's wrong with the above approach? How do you fix this?
Karsten