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

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>

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.

Why are comopnents of another form validated with JSF 2.3?

I just upgraded to JSF 2.3 & Wildfly 14 (from 2.0 and 13) and primefaces 6.2.5.
I noticed a strange behavior when i use a command button. I have 2 forms and when a push the button of the first form, the input of the second form is validated and the error (in this case required errors) are displayed in a p:message :
<h:form id="form1" prependId="false">
<p:commandButton id="save" value="Save" actionListener="#{myBean.save()}" update="#form">
<f:actionListener binding="#{myBean.reloadResults()}" />
</p:commandButton>
<p:messages id="msgs" severity="error,warn" escape="false">
<p:autoUpdate />
</p:messages>
...
</h:form>
<p:dialog >
<h:form id="form2" >
<p:messages severity="error,warn" escape="false">
<p:autoUpdate />
</p:messages>
<div>
<p:calendar id="myDate" value="#{myBean.myDate}" required="true" />
</div>
...
</h:form>
</p:dialog>
I was expecting only the content of the first form to be processed and validated. This was the case with wildfly 13 and jsf 2.0.
Any idea?
You have not specified attribute process in your command button. Default value of this is #all which will validate all Forms.
Please use process="#form" to avoid validation and process of other form.
Updated code is as below:
<p:commandButton id="save" value="Save" actionListener="#{myBean.save()}" update="#form" process="#form">
<f:actionListener binding="#{myBean.reloadResults()}" />
</p:commandButton>
I have to apologize for not posting the entire code but it would have been to big. I found out what the problem was. It's related to this bug:
https://github.com/primefaces/primefaces/issues/4122
I have a panelgrid of 4 columns but with 10 elements in it.
The whole ajax communication was then broken. Fix is coming in PF 6.3

ActionListener method not called from dialog CommandButton

I've this code:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui" >
<h:form>
<h1 class="page-header "> <i class="fa fa-tachometer"></i> Dashboard</h1>
<p:outputPanel id="contentPanel">
<p:commandButton value="Añadir caso de prueba" actionListener="#{testCaseBean.prepareCreateTestCase}" oncomplete="PF('addTestCaseDialog').show();" process="#this" update=":dialog"/>
<p:dataTable>
</p:dataTable>
</p:outputPanel>
</h:form>
<p:dialog header="Crear caso de prueba" modal="true" id="dialog" widgetVar="addTestCaseDialog" closable="false">
<h:form id="addTestCaseDialogForm">
<p:panelGrid columns="4" styleClass="ui-noborder">
<p:outputLabel for="testCaseName" value="Nombre del caso de prueba:"/>
<p:inputText id="testCaseName" value="#{testCaseBean.testCase.testCaseName}" required="true"/>
<p:outputLabel for="assignedTask" value="Tarea relacionada:"/>
<p:inputText id="assignedTask" value="#{testCaseBean.testCase.assignedTask}" required="true"/>
<p:outputLabel for="isRegressive" value="Regresivo:" />
<p:selectBooleanCheckbox id="isRegressive" value="#{testCaseBean.testCase.isRegressive}"/>
</p:panelGrid>
<p:commandButton value="Guardar" actionListener="#{testCaseBean.createTestCase}" oncomplete="PF('addTestCaseDialog').hide()" process="addTestCaseDialogForm"/>
<p:commandButton value="Cancelar" onclick="PF('addTestCaseDialog').hide()" immediate="true" />
</h:form>
</p:dialog>
And I'm having a problem: the actionListener method from the dialog commandButton is not being called and I don't know why.
If put this in then commandButton:
<p:commandButton value="Guardar" actionListener="# {testCaseBean.createTestCase}" oncomplete="PF('addTestCaseDialog').hide()" process="#this"/>
The method is called, but the form is not processed.
Any help?
Thanks!
PrimeFaces provides a partial rendering and view processing feature based on standard JSF 2 APIs
to enable choosing what to process in JSF lifecyle and what to render in the end with ajax.
There are a couple of reserved keywords which serve as helpers.
-#this : Component that triggers the PPR is updated
-#parent: Parent of the PPR trigger is updated.
-#form: Encapsulating form of the PPR trigger is updated
-#none: PPR does not change the DOM with ajax response.
-#all: Whole document is updated as in non-ajax requests.
In Partial Page Rendering, only specified components are rendered, similarly in Partial Processing
only defined components are processed. Processing means executing Apply Request Values,
Process Validations, Update Model and Invoke Application JSF lifecycle phases only on defined
components.
Back to your problem, you should use process #form
Hope this could help you.
I also see you have some fields marked as required. If some required fields are not filled up, the validation fails and the action listener is not called.
But if there are no proper < h:messages> tags in your pages or templates, the validation errors are not displayed anywhere !!
Ensure you also have a proper < h:messages> or < p:messages> to show any possible validation errors.
We spend several hours with this issue until we figured it out ...
Add process="#this" to the commandButton.
Also, study this guide from BalusC:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated

PrimeFaces: selectOneButton is cleared on validation error

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.

Primefaces dataTable filter works only once

im using Primefaces 3.5 to create a dataTable with filters.
<h:form id="table">
<div class="showRuleStyle">
<p:dataTable id="RuleTable" var="e" value="#{ruleListBean.rules}" filteredValue="#{ruleListBean.filteredRules}" styleClass="ruleTable" paginator="true" paginatorPosition="bottom" rows="15" emptyMessage="Keine Einträge gefunden.">
<p:column id="companyColumn" headerText="Name" filterBy="#{e.name}" filterOptions="#{ruleListBean.filterNameOptions}" >
<h:outputText value="#{e.name}"></h:outputText>
</p:column>
...
<p:column>
<f:facet name="header"></f:facet>
<h:commandButton id="DeleteRuleButton" value="Löschen" styleClass="buttondefault" action="#{ruleListBean.removeRule(e)}" update=":table"></h:commandButton>
</p:column>
</p:dataTable>
</div>
</h:form>
Now, i get the table as intended and can choose an filter which updates the table. But now, if i try to choose a different filter or select the empty filter, nothing happens. If I click the button, it works again, which i think is because of the update of the form.
I tried to add
<p:ajax event="filter" update=":table">
and other events, but it won't work.
Any suggestions?
Greets
Alex
What is the scope of the ruleListBean? I've tried your code and it worked as expected (without the p:ajax).
My ruleListBean is in view scope.
It is suggested to use a scope longer than request like viewscope to
keep the filteredValue so that filtered list is still accessible after
filtering. (PrimeFaces User’s Guide pg. 135)
NOTE: Change h:commandButton to p:commandButton so that you can use the update feature.