PrimeFaces: selectOneButton is cleared on validation error - primefaces

I have a wizard tab and a few fields in it. Some of them are required.
There is also a selectOneButton. The problem is when I have some required fields empty and some value selected in selectOneButton - when the validation fails on form submit, it gets "unclicked", i.e. nothing is selected. I suspect that the whole form gets updated but other components still hold the visible value.
What am I doing wrong or maybe someone have had the same problem?
I use PrimeFaces-5.0.RC2
Here is the code:
<p:tab title="Service params" id="firstTab">
<h:panelGrid columns="2">
Name *
<p:inputText value="#{serviceMB.service.name}" label="Name" required="true" maxlength="150"/>
Unit
<p:selectOneButton value="#{serviceMB.service.unit}" converter="serviceUnitConverter"
filter="true" filterMatchMode="contains" label="Unit"
id="unitMenu"
required="true">
<f:selectItems value="#{serviceMB.allServiceUnits}" var="unit"
itemLabel="#{unit.name}"
itemValue="#{unit.code}"/>
<p:ajax event="change"
update=":addServiceForm:priceListPanel"
process="#this"/>
</p:selectOneButton>
</h:panelGrid>
<p:commandButton value="Next" icon="ui-icon-triangle-1-e" iconPos="right" type="button" onclick="PF('serviceWizard').next();"/>
So Unit is the component which value is cleared. I really have no idea why, so I moved to selectOneMenu instead which is less preferable in my case.

Related

Why JSF form maintain the validation styles even if has values on it?

I have a form (frmAddPax) to add some users data. This data could be submited manual or vía a barcode reader. When the button "Escanear" is pressed this one calls a dialog with another form (frmScan).
This form read some data from a barcode reader and this data is processed in the managed bean. The data creates an object that is used in the original form (frmAddPax).
The problem is all the form has the styling as there wasn't any data on it, all the mandatory fields have the required="true" attribute.
If I press the "Escanear" button again and scan the same data it shows the form just fine.
I think this could be because before the data is ready updated in the form the validation process happend, but as I have seen in some questions the action and actionListener events happend before the update process so I have no clue.
This is the code of the form:
<h:form id="frmAddPax"
rendered="#{MB.renderStatus.isRenderFormAddPax()}">
<p:panelGrid styleClass="no-border">
<p:row>
<p:column>
<h:outputText
value="#{label['manageVipLoungeEntrance.addPassenger.firstName']} />
</p:column>
<p:column>
<p:inputText required="true"
value="#{manageVipLoungeEntranceExtMB.passenger.firstName}"
style="text-transform: uppercase;" converter="upperCaseConverter">
<f:ajax event="blur" update="#this" render="#this" />
</p:inputText>
</p:column>
...
...
<!-- BOTON ESCANEAR AGREGAR PASAJERO -->
<p:column>
<p:commandButton inmediate="true"
value="#{label['manageVipLoungeEntrance.addPassenger.button.scan']}"
onclick="showLocalDate()" update=":frmScan"
actionListener="#{manageVipLoungeEntranceExtMB.clear}"
oncomplete="{wgvScan.show()}" />
</p:column>
<!-- BOTON ESCANEAR AGREGAR PASAJERO -->
</p:row>
</p:panelGrid>
This is the code for the call that made the "Escanear" button:
<p:commandButton inmediate="true"
value="#{label['manageVipLoungeEntrance.addPassenger.button.scan']}"
onclick="showLocalDate()" update=":frmScan"
actionListener="#{manageVipLoungeEntranceExtMB.clear}"
oncomplete="{wgvScan.show()}" />
And this is the code for the widtget that process the barcode read and updates the original form with the data processed.
<p:dialog widgetVar="wgvScan" modal="true" showEffect="fade"
closeOnEscape="true" resizable="false">
<h:form id="frmScan">
<p:graphicImage value="../resources/images/barCode.png"
rendered="#{manageVipLoungeEntranceExtMB.showTablePassenger!=true}" />
<p:inputText id="itbarcode"
rendered="#{manageVipLoungeEntranceExtMB.showTablePassenger!=true}"
value="#{manageVipLoungeEntranceExtMB.barCode}" onfocus="true"
autocomplete="off" styleClass="insertData"
style="background:#ffffff; position:absolute;left:-7000;" />
<p:commandButton id="cmdReadBarcode" style="display:none"
onclick="showLocalDate()"
actionListener="#{manageVipLoungeEntranceExtMB.readBarCode}"
update=":frmAddPax :growl">
</p:commandButton>
<p:defaultCommand target="cmdReadBarcode" />
...
</h:form>
[EDIT]
#alibttb answer get me to the solution.
I added a remoteCommand before the button that calls the dialog to listen the scanner.
<p:remoteCommand name="refreshForm" process=":frmAddPax" update=":frmAddPax" />
<p:commandButton
value="#{label['manageVipLoungeEntrance.addPassenger.button.scan']}"
onclick="showLocalDate()" process="#this" update=":frmScan"
actionListener="#{manageVipLoungeEntranceExtMB.clear}"
oncomplete="{wgvScan.show()}" />
</p:column>
And in the dialog with the form that process the barcode I added a onHide attribute calling the remoteCommand.
I change the enclouse of the dialog-form to form-dialog as was sugested.
<h:form id="frmScan">
<p:dialog widgetVar="wgvScan" modal="true" showEffect="fade"
closeOnEscape="true" resizable="false" onHide="refreshForm()">
What happens when you click the Escanear button is that you are processing the whole form, thus submitting all the fields with empty values, this will cause validation errors, your button is immediate so what happens is the following:
actionListener is immediate so it's called first and the managed bean is filled with data from a barcode scanner.
the form data is being validated and it's not valid so the inValid flag is set on all the inputs.
the response is created on the server containing an update for the form, showing the new values from the managed bean and the inValid state of the inputs from the validation process.
notice that the submitted data (empty values) is not applied to the model as it's not valid.
to fix this, just use partial processing feature on your button, and remove the immediate="true", it's just a bad design.
just replace immediate="true" with process="#this" in the Escanear button.
If you're not familiar with partial processing feature of JSF and primefaces you should give it a look.
if you really need to submit the form for validation after the scan is complete then you need to use a p:remoteCommand that submits the form after the actionListener is complete:
<p:remoteCommand name="validateForm" process="#form"/>
<p:commandButton value="#{label['manageVipLoungeEntrance.addPassenger.button.scan']}"
onclick="showLocalDate()" update=":frmScan" process="#this"
actionListener="#{manageVipLoungeEntranceExtMB.clear}"
oncomplete="{wgvScan.show()}" />
and in the other form frmScan do:
<h:form id="frmScan">
<p:dialog widgetVar="wgvScan" modal="true" showEffect="fade"
closeOnEscape="true" resizable="false" onHide="validateForm()">
....
....complete your code
the name of the p:remoteCommand becomes a javascript function that can be called back once the scan dialog is hidden.
Note bring up the dev console in your browser and watch the two requests one for updating the form and closing the dialog and the other one caused by p:remoteCommand to validate the form.
Note 1 (not related to your question) that I used the frmScan to enclose p:dialog this is the right way to do it, the form should surround the dialog not the other way around.

Primefaces Tabview resetting inputs

I use primeface 3.5. I have a tabview and each tabview has got inputMasks with a form. I want to reset inputMask when i change the tab. I listen ontabchange event and reset value to="" but bean reset values but View doesn't reset.
<p:tabView id="tabViewOS" binding="#{docData.tabView}" dynamic="true" cache="true" rendered="#{userData.opRendered}">
<p:ajax event="tabChange" listener="#{docData.onTabChange}" immediate="true"/>
<p:tab id="tab1" title="AB">
<h:form id="ABForm">
<h:panelGrid id="abgrid" columns="3" cellpadding="5">
<h:outputText value="AB NO: " />
<p:inputMask value="#{docData.abNo}" mask="999-99999999"
id="ABinput" required="true"
</p:inputMask>
<p:message id="msgAB" for="ABinput" showDetail="true" autoUpdate="true" />
<h:outputText value="" />
<p:commandButton value="GETİR" style="float:right;" ajax="false"
action="#{docData.getDoc}" />
</h:panelGrid>
</h:form>
</p:tab>
public void onTabChange(TabChangeEvent event) {
this.activeTabIndex = tabView.getChildren().indexOf(event.getTab());
FacesContext.getCurrentInstance().renderResponse();
System.out.println(this.activeTabIndex);
this.abNo="";
documents.clear();
}
Try changing the way the event is called. Instead of immediate=true use process="#this".
Change this:
<p:ajax event="tabChange" listener="#{docData.onTabChange}" immediate="true"/>
To this:
<p:ajax event="tabChange" listener="#{docData.onTabChange}" process="#this" update="ABinput"/>
i guess as you said -dynamic="true" cache="false">- is solve my problem. Actually I tested program faulty, my problem has already solved. I think in my case cause of this situation cache=false as documentation said. Thank you.
Have a look at the primefaces documentation on p:tabView. On the one hand you have the property dynamic which specifies if the content of a tab is loaded with AJAX when you select some tag. On the other hand there is the property cache which specifies wheter or not the content of a tab is only dynamically loaded the first time you select a tab.
So regarding this informations setting dynamic="true" cache="false" on the p:tabView should do the trick for you.
Another interesting property for you would be activeIndex. As I see you are setting the index of the active tab manually on tab change. If you can submit tabview on tabchange and you have set activeIndex="#{docData.activeTabIndex}" the active tabindex is tracked automatically. Have a look at the documentation if this fits your requirements.

jsf standard converter along with primefaces select one menu

When the "select" option of the select one menu is selected, the default value is saved in DB as 0. Can I change this to null?
The value of select one menu is bound to a bean property. To achieve this, I have used the converter attribute of the select one menu component. But it does not seem to convert empty string to null. What am I missing?
<p:panelGrid columns="2" >
<p:outputLabel value="District" />
<p:selectOneMenu value="#{cJData.cJ.dC}" converter="javax.faces.Long">
<p:ajax listener="#{cJActionHandler.selectDC}"/>
<f:selectItem itemLabel="Select" itemValue="" />
<f:selectItems value="#{cJData.DCs}" var="coun"
itemLabel="#{coun.name}" itemValue="#{coun.id}" />
</p:selectOneMenu>
</p:panelGrid>
Use the following
<f:selectItem itemLabel="Select" itemValue="#{null}" />
As the docs of LongConverter#getAsObject say - this is the method which is called when you submit th value - the Long converter will convert only null to null.

ui:repeat and c:foreach dont return the same organisation

I have a loop that contains a list of properties
I would like to display this list on 2 columns, but I can not.
  they are displayed by unordered, against if I use c: For Each place of ui: repeat
the problem is resolved
<p:panel id="panlecart2" header ="Caracteristique selon la categorie" toggleable="true" rendered="true" style="width=900px;">
<h:panelGrid id="panlecart" columns="2" cellpadding="5" rendered="true" style="width=900px;">
<ui:repeat var="var1" value="#{composantbean.categorie.proprietes.toArray()}">
<h:outputText value="#{var1.nomProp }(#{var1.unite} )" />
<h:inputText value="" />
</ui:repeat>
</h:panelGrid>
</p:panel>
Haw can I fixe the problem .helpe please :)
You could switch to using <h:dataTable> to iterate over the components:
<h:dataTable var="var1" value="#{composantbean.categorie.proprietes.toArray()}">
<h:column>
<h:outputText value="#{var1.nomProp }(#{var1.unite} )" />
</h:column>
<h:column>
<h:inputText value="" />
</h:column>
</h:dataTable>
Enclose it within a <p:panel> to make it work. Otherwise, make use of <c:forEach> as it's a good fit for your use case.
ui:repeat is rendered in a later phase than c:forEach. Here's an explanation.
c:forEach is the way to go here, since this is invoked in view build time.
ui:repeat is invoked during view render time, so p:panel would have no knowledge of the data being created by ui:repeat.

why isn't this jsf/ajax code submitting the values?

I'm embedding here a simplified version of a code that is not working for me.
What happens here is that there are 2 forms.
The first form contains an ajaxified <h:commandLink> (Using <f:ajax>)
The second form contains a form with values.
When the <h:commandLink> is pressed, the values in the second form are supposed to be submitted.
What happens in practice is that values are retrieved (the getter function is run) but are not submitted (the setter function never runs).
The <f:ajax> runs because I can see the listener method running and the second form does get rerendered after clicking the <h:commandLink> but, again, the setter functions are never run.
<body>
<h:form prependId="false">
<h:panelGroup >
<h:commandLink >
<f:ajax event="click"
execute=":form_with_values_to_update" render=":form_with_values_to_update"
listener="#{mrBean.clickListenerAction}" />
Do something
</h:commandLink>
</h:panelGroup>
</h:form>
<h:panelGroup>
<h:form id="form_with_values_to_update">
<fieldset>
<ui:repeat value="#{mrBean.aMemberOfBean.aListInAMemberOfBean}" var="listItem">
<h:panelGroup>
<h:outputText value="#{listItem.label}" />
<h:inputText id="contact_details_input"
value="#{listItem.value}" />
</h:panelGroup>
</ui:repeat>
</fieldset>
</h:form>
</h:panelGroup>
</body>
P.S - Using MyFaces JSF 2.1
The commandlink/button has to go in the same form as where the data of interest is in.
If that's not an option due to some design or business restrictions, then you need a second commandlink/button. First move the original commandlink/button back in the right form, give it an id and hide it using CSS display: none;.
Then put the second commandlink/button in the other form which does something like
<h:commandLink onclick="document.getElementById('form_with_values_to_update:linkid').click(); return false;">
Do something
</h:commandLink>