Primefaces autocomplete inside a custom composite component, behaving as without any suggested result - jsf

We use a lot of modals in a JSF project, so we made a simple custom component to embed the needed HTML code. Nothing complicated, just a wrapper without any logic:
<cc:interface>
<cc:attribute name="modalId" type="java.lang.String" required="true" />
<cc:attribute name="styleClass" type="java.lang.String" />
...
</cc:interface>
<cc:implementation>
<div id="#{cc.attrs.modalId}" class="modal fade">
<div class="modal-dialog modal-lg modal-dialog-centered #{cc.attrs.styleClass}">
...
<cc:insertChildren />
...
</div>
</div>
</div>
In one of this modal, we use a primefaces autocomplete component:
<my:modal modalId="myModal">
...
<p:autoComplete value="#{myBean.myValue}" multiple="true" completeMethod="#{myBean.myMethod}"
converter="#{myBean.myConverter}" forceSelection="true" unique="true" appendTo="#this" emptyMessage="no result"
var="example" itemLabel="#{example.name}" itemValue="#{example}" />
...
</my:modal>
In this state, the dropdown displaying the results behaves as if there were no result at all (the component emptyMessage is shown).
Of course, I checked the completeMethod, and it is returning results.
If I move the p:autocomplete outside the my:modal component, or if I replace the modal component by its pure HTML counterpart, everything works fine. So I guess our my:modal component is the cause of the fuss.
We're on a JSF 2 and Primefaces 11 project. A lot of other primefaces components (tree, selectBooleanCheckbox, fileUpload, dataTable, ...) are used without any issue in our modals.
What am I missing here?

Related

JSF 2.3 Facet in Composite Component with wrong ID

I have the following simple code in a composite component (using Mojarra 2.3.9 / Primefaces 7):
<composite:implementation>
<h:form id="form">
<composite:insertChildren />
<ui:fragment rendered="#{!empty cc.facets.actions}">
<div class="actions">
<composite:renderFacet name="actions" />
</div>
</ui:fragment>
</div>
</h:form>
</composite:implementation>
And the following part is used in a page, trying to fill the composite form with life:
<cc:compForm id="mySpecialForm">
<f:facet name="actions">
<p:commandButton
id="myBtn"
value="Submit"
process="#form"
update="#form">
</p:commandButton>
</f:facet>
</cc:compForm>
The form and all the children are rendered correctly and working quite well. But the button in the renderFacet block has - in my opinion - a wrong client ID, because instead of:
mySpecialForm:form:myBtn
the button only gets the following clientId:
mySpecialForm:myBtn
This leads to an error rendering the page:
Cannot find component for expression "#form" referenced from
"mySpecialForm:myBtn".:
org.primefaces.expression.ComponentNotFoundException: Cannot find
component for expression "#form" referenced from
"mySpecialForm:myBtn".
Am i doing something wrong or is this a bug in JSF/Primefaces? I also tried to configure the componentType to an #FacesComponent extending from UIForm, but in this case no form will be rendered at all.
Update 1:
I tried to create a "minimal, reproducible example (reprex)" like mentioned by Kukeltje. All what is needed are those 2 Parts in a web application (both files under resources):
cc/compForm.xhtml:
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:composite="http://xmlns.jcp.org/jsf/composite">
<composite:interface name="compForm" displayName="A composite form">
<composite:facet name="actions" />
</composite:interface>
<composite:implementation>
<h:form id="form">
<composite:insertChildren />
<composite:renderFacet name="actions" />
</h:form>
</composite:implementation>
</html>
compFormTest.xhtml:
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:cc="http://xmlns.jcp.org/jsf/composite/cc">
<cc:compForm id="mySpecialForm">
<h:inputText id="inputParam" value="" />
<f:facet name="actions">
<h:commandButton id="myBtn" value="Test" />
</f:facet>
</cc:compForm>
</html>
All todo is call the .xhtml page: http:localhost/YOUR_APP/compFormTest.xhtml.
After using it (at least with Mojarra JSF implementation), the input field has the following correct client ID mySpecialForm:form:inputParam. But the command button retrieves another client ID outside the form: mySpecialForm:myBtn, what is a bug from my point of view, regarding the JSF VDL: " ... will be rendered at this point in the composite component VDL view.".
But as i downstriped the example files, it is clearly not a primefaces problem, because the wrong client ID is also included, if using the standard h:commandButton component.
Perhaps someone can use the mentioned 2 files above in a MyFaces environment to check if the behaviour differs or is the same?
Or has someone a workaround in mind? Using an additional #FacesComponent and moving the button from facet to the right spot under the form leads to the following "funny" duplicate ID error:
"Cannot add the same component twice: mySpecialForm:form:myBtn" (at least the client ID was what i expected in the first place)

Native JSF color input widget

According to Mozilla's Developer Network, there is an HTML input element with type="color" since HTML 4.01. It can be used in a form like this:
<form>
<input type="color"/>
</form>
I tested this with recent browsers (Firefox 52, Chromium 65 and Opera 49) and all were working well with plain HTML. They provide a button and on click a popup-window is opened to select a color.
Now the question: how can I use this color input with JSF without a third-party library?
I couldn't find any suitable component for neither JSF 2.2 nor 2.3. I know there is PrimeFaces <p:colorPicker> and there are probably other third-party components as well. But I need/want plain JSF/Mojarra.
I found this answer, which describes the use of passthrough attributes. With this, it is actually quite simple to create a basic composite-component which does exactly what I need:
<ui:component xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
xmlns:cc="http://xmlns.jcp.org/jsf/composite">
<cc:interface>
<cc:attribute name="value" type="java.lang.String" required="true" />
<cc:clientBehavior name="clientEvent" targets="colorInput" event="change" />
</cc:interface>
<cc:implementation>
<h:inputText id="colorInput" a:type="color" value="#{cc.attrs.value}" />
</cc:implementation>
</ui:component>
(See also BalusC's answer on details about <cc:clientBehavior>.)

Display some of the items striked in primefaces multiselect checkbox dropdown

I am working on primefaces application, where I have to implement a functionality to display list of user objects in dropdown and user can select multiple user objects and filter it.
If the user is deleted or inactive I need to display that user value in striked out.
I seen this link and implemented same way but nothing worked
Different colors of options in selectOneMenu (Primefaces)
If I used this below selectManyMenu, dropdown is coming in page load itself, but the dropdown should come when the user selects the dropdown
https://www.primefaces.org/showcase/ui/input/manyMenu.xhtml
As this functionality exist in many places I wrote a custom dropdown:
<cc:interface>
<cc:attribute name="id" required="true"/>
<cc:attribute name="value" required="true"/>
<cc:attribute name="converterId" type="java.lang.String"/>
</cc:interface>
<cc:implementation>
<div class="userCheckBoxMenu">
<div style="display: inline-block; position: relative;">
<p:selectCheckboxMenu
var="t" filter="true" filterMatchMode="contains" showCheckbox="true">
<f:selectItems value="${cc.attrs.value}" var="u" itemLabel="#{myBean.formatUser(u)}" itemValue="#{u}"/>
<p:column>
<h:outputText value="#{myBean.formatUser(t)}" styleClass="#{myBean.isValidUser(t)} ? 'white-background' :'invalid-user-text'" />
</p:column>
<f:converter converterId="converterId" />
</p:selectCheckboxMenu>
</div>
</div>
</cc:implementation>
Dropdown is coming but invalid user value still showing normally, not striked out.
When I see the generated html, for p:selectOneMenu it's generating table for the dropdown, but for p:selectCheckBoxMenu it's generating div element, and the column is generating another dropdown but it's hidden.
Confused about it, how to handle this situation?
Thanks in advance!!!!!!!

how to awoid duplication ajax call in composite component

May be I make a fundamental mistake about jsf 2.2 specification, if so I would like to learn the correct solution of my problem. I use mojarra 2.2.9 immplementation, primemafaces 5.0.
I have a composite component with input, which always process on change event:
<cc:interface>
<cc:attribute name="value" type="java.lang.String" required="true"/>
<cc:clientBehavior name="change" event="change" targets="input"/>
</cc:interface>
<cc:implementation>
<span id="#{cc.clientId}">
<p:inputText value="#{cc.attrs.value}">
<p:ajax update="#this"/>
</p:inputText>
/* some ather component */
</span>
</cc:implementation>
And now in some cases I want to use additional listener and update some component outside cc, like clientBehavior solution:
<my:inp value="#{bean.value}">
<p:ajax event="change" listener="#{bean.listener}" update="someComponentOnPage" process="#this">
</my:inp>
Using that solution, I have 2 ajax call on 1 change event: first inside cc, second outside. Is there a solution to call ajax only once (if exist clientBehavior then not use ajax that inside)?
P.S.: sorry for my english...

Using id-attribute in JSF 2 composite component with targets

I am trying to create a JSF 2.1 composite component for a button:
<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:composite="http://java.sun.com/jsf/composite"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jstl/core">
<composite:interface>
<composite:attribute name="id" required="true" type="java.lang.String" />
<composite:attribute name="label" required="true" type="java.lang.String" />
<composite:attribute name="action" method-signature="java.lang.String action()" targets="#{cc.attrs.id}" />
</composite:interface>
<composite:implementation>
<a4j:commandLink id="#{cc.attrs.id}">
<span style="linkButton"><h:outputText value="#{cc.attrs.label}" /></span>
</a4j:commandLink>
</composite:implementation>
</html>
The problem I have with this code is that it gives the following exception when the page is rendered:
java.lang.ClassCastException: javax.faces.component.UINamingContainer cannot be cast to javax.faces.component.ActionSource2
at com.sun.faces.application.view.FaceletViewHandlingStrategy$MethodRetargetHandlerManager$ActionRegargetHandler.retarget(FaceletViewHandlingStrategy.java:1536)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.retargetMethodExpressions(FaceletViewHandlingStrategy.java:689)
at com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler.applyNextHandler(CompositeComponentTagHandler.java:201)
at org.richfaces.view.facelets.html.BehaviorsAddingComponentHandlerWrapper.applyNextHandler(BehaviorsAddingComponentHandlerWrapper.java:53)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:196)
...
When I replace the #{cc.attrs.id} in id and targets attribute with a defined String like myId then the component works as expected but this makes it not reusable in the same page and thus eliminates the wohle sense in creating a composite component in the first place.
Did I miss anything here?
In the JSF component tree, the #{cc.attrs.id} is already used by <cc:implementation> itself. You're not supposed to reuse any used component ID on another component. Your concrete functional requirement is unclear, the complaint "not reusable in the same page" makes really no sense as it works perfectly fine (have you actually tried it and investigated the produced HTML output?), so it's hard to understand what problem exactly you're facing. Perhaps you completely overlooked that composite components implicitly inherit from NamingContainer and already prepend their own id to those of children, like as <h:form>, <h:dataTable>, etc also do?
If your sole requirement is being able to reference the composite component from outside by ajax as in <f:ajax render="compositeId" />, then you need to wrap the body of <cc:implementation> in a plain vanilla HTML <span> or <div> as follows with the #{cc.clientId} instead:
<div id="#{cc.clientId}">
See also:
Rerendering composite component by ajax

Resources