It appears that primefaces <p:tree> is not an EditableValueHolder, even though it offers the ability to make the tree selectable. To me this seems like the very definition of EditableValueHolder as it both holds values (the list of nodes that are selected) and is editable (you can change the selection). In making the tree selectable, it basically turns it into a selectOneXxx/selectManyXxx. This is the fashion in which I use this widget. However, not being an EditableValueHolder, I cannot attach a validator to it directly. I could add validation to the form submission action with an actionListener but then it is out of the appropriate lifecycle phase and is much more difficult to get at the UITree component to check for attributes like the i18n message for failed validation. Has anyone dealt with this before? What do you do?
———- EDIT ———-
I found an issue posted in the primefaces bug tracker that seems releated:
And a forum post:
———- EDIT ———-
This is the solution I came up with. Some of the jQuery is pretty hairy as it uses server side el to generate the client side javascript. But for the most part it works. Just have to figure out why an empty array skips validation… but thats another story.
<h:panelGroup id="pnpCois" styleClass="pnp-input-group pnp-cois">
<h:outputLabel for="inputCois"
value="#{i18n['communities-of-interest']}" />
<p:tree id="inputCois"
value="#{subscriptions.selected.coiTreeRootNode}" var="node"
selectionMode="checkbox"
selection="#{subscriptions.selected.selectedCoiNodes}">
<p:ajax event="select" process="@this :#{component.clientId}_validator" update="@this"
onstart="$('##{component.clientId}_validator'.replace(':','\\:')).val($('##{component.clientId}_selection'.replace(':','\\:')).val());" />
<p:ajax event="unselect" process="@this :#{component.clientId}_validator" update="@this"
onstart="$('##{component.clientId}_validator'.replace(':','\\:')).val($('##{component.clientId}_selection'.replace(':','\\:')).val());" />
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
<h:inputHidden id="inputCois_validator">
<f:converter converterId="asias.stringCsvToArray" />
<f:validator validatorId="asias.atLeastOneSelected" />
<f:attribute name="atLeastOneSelectedMessage"
value="#{i18n['at-least-one-coi-must-be-selected']}" />
</h:inputHidden>
</h:panelGroup>
———- EDIT ———-
After working through some suggestions with BalusC, I think I’m gonna give up on <p:tree> and find another way… 🙁
You can trick it with a required hidden input field whose value is altered on node click. You can use the
selectionsproperty of the<p:tree>widget variable to get the available selections as an array.E.g.
The
'ok'value is purely arbitrary. The point is that the hidden field is filled, so that therequiredvalidator doesn’t get triggered.