I try to add a contextMenu in a tree to perform a custom action. This tree is implemented inside an overlaypanel. What i observed is that the contextMenu only appears in random situations like after selecting and unselecting some elements on the tree. Any Idea?
<p:overlayPanel id="advancedSearchPanel"
styleClass="ui-advanced-search-overlay"
for="advancedSearch"
hideEffect="fade"
my="right top"
widgetVar="advancedSearchPanelWidgetVar" >
<ui:include src="/search/advancedSearch-form.xhtml"/>
</p:overlayPanel>
advancedSearch-form
<p:panelGrid id="panelAdvanced" styleClass="borderless">
...
<p:row>
<p:column colspan="4">
<p:outputLabel value="#{text['searchForm.classifiers']}" for="treeClassifier" styleClass="paddingLabelGrid"/>
<p:contextMenu id="contextSearch" for="treeClassifier">
<p:menuitem value="Escolha todos" update=":searchForm:treeClassifier" actionListener="#{navBarController.displaySelectedSingle}"/>
</p:contextMenu>
<p:tree id="treeClassifier"
value="#{navBarController.rootClassifier}"
var="node" selectionMode="checkbox"
selection="#{navBarController.selectedClassifiers}"
style="height: 200px;width: 540px; margin-bottom: 0px; overflow: auto"
propagateSelectionDown="false"
propagateSelectionUp="false">
<p:ajax event="select" update=":searchForm:btnSearch"/>
<p:ajax event="unselect" update=":searchForm:btnSearch"/>
<p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed">
<h:outputText value="#{node.description}(#{node.code})"/>
</p:treeNode>
</p:tree>
</p:column>
</p:row>
...
Try like that:
my advancedSearch-form.xhtml
<?xml version="1.0" encoding="UTF-8" ?>
<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:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<h:form id="searchForm">
<p:panelGrid id="panelAdvanced" styleClass="borderless">
<p:row>
<p:column colspan="4">
<p:contextMenu id="contextSearch" for="treeClassifier">
<p:menuitem value="Escolha todos" update="treeClassifier" actionListener="#{treeView.displaySelectedSingle}"/>
</p:contextMenu>
<p:tree id="treeClassifier" value="#{treeView.root}" var="node" selectionMode="checkbox" selection="#{treeView.selectedClassifiers}"
style="height: 200px;width: 540px; margin-bottom: 0px; overflow: auto"
propagateSelectionDown="false"
propagateSelectionUp="false">
<p:ajax event="select" global="false" listener="#{treeView.reset}" />
<p:ajax event="unselect" global="false" listener="#{treeView.reset}" />
<p:ajax event="contextMenu" global="false" listener="#{treeView.onContextMenu}"/>
<p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed">
<h:outputText value="#{node.nodeName}"/>
</p:treeNode>
</p:tree>
</p:column>
</p:row>
</p:panelGrid>
</h:form>
</ui:composition>
And my bean:
@Component(value="treeView")
@Scope(value = "session")
public class TreeView implements Serializable {
private TreeNode[] selectedClassifiers;
public TreeNode[] getSelectedClassifiers() {
return selectedClassifiers;
}
public void setSelectedClassifiers(TreeNode[] selectedClassifiers) {
this.selectedClassifiers = selectedClassifiers;
}
private TreeNode selectedClassifier;
public void reset(){
selectedClassifier = null;
}
public void displaySelectedSingle(){
if(selectedClassifier != null){
List<TreeNode> selected = new ArrayList<TreeNode>();
for(int i=0; i < selectedClassifiers.length; i++){
selected.add(selectedClassifiers[i]);
if(selectedClassifiers[i].equals(selectedClassifier))
selected.addAll(selectionRecursive(selectedClassifier));
}
selectedClassifiers = selected.toArray(new TreeNode[selected.size()]);
}
}
public void onContextMenu(NodeSelectEvent event){
selectedClassifier = event.getTreeNode();
}
public List<TreeNode> selectionRecursive(TreeNode node){
List<TreeNode> selected = node.getChildren();
for(TreeNode child : node.getChildren()){
selected.addAll(selectionRecursive(child));
child.setSelected(true);
}
return selected;
}
}
Method selectionRecursive(TreeNode node) need debug but in my case all work great.
I'm not sure about what you really want to achieve, but:
You are using 2 features of the tree component.
Use of both features at the same time is not currently supported bt Primefaces. Whenever you right-click a node, the contextMenu shows up, then the node is selected/deselected. The contextMenu does not shows up if you click outside a node (container background or between nodes)
If you want a single contextMenu for the whole tree (ie Select All, Unselect All, Select whatever...) so just remove the for attribute on contextMenu :
instead of :
<p:contextMenu id="contextSearch" for="treeClassifier">
just write
<p:contextMenu id="contextSearch">
In this way, the contextMenu appears wherever you right-click on the container (p:column
in your case).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With