How to prevent/stop submit of commandbutton when having on going AJAX-call - jsf

I have a form with a few different text fields which the user needs to fill in to be able to go to the next step. The next step of the page is accessed by clicking a commandbutton "Next" and should only be enabled when all of the fields are valid (validated on the server).
The problem is that the user can click the "next step" button directly after changing a field with valid input to invalid input, without loosing focus on the field, causing the validation to not get triggered in time to prevent the user to go to the next step.
Here is an example of one of the fields, together with the commandbutton doing the submit.
<p:inputTextarea id="lineFreeText" value="#{line.freeText}" rows="1" disabled="#{facesContext.validationFailed and component.valid}"
maxlength="#{itemConstant.MAX_FREE_TEXT_LENGTH}" counter="freeTextCounter"
counterTemplate="{0}/#{itemConstant.MAX_FREE_TEXT_LENGTH}" rendered="#{showFreeText and !line.hasItemForm()}" validator="freeTextValidator" validatorMessage="#{messages.freeTextRequired}" requiredMessage="#{messages.freeTextRequired}">
<p:ajax event="change" process="#this" listener="#{cartController.saveLine(line)}" update="#form cartForm lineFreeText lineEditedSymbols lineFreeTextMessage #([id$=nextStepBtn])" />
</p:inputTextarea>
<h:commandButton value="#{messages['checkout.nextStep']}" id="nextStepBtn" rendered="#{cartController.size() gt 0 and !clientContext.OCIRequest}"
onclick="$('.jqRealNextStepButton').click();" style="border: 2px solid #008091; padding: 0.5em;"
styleClass="ju-button" disabled="#{clientContext.client.visitor or checkoutDeliveryDateController.disableNextButton() or totalMinAmountNotMet or facesContext.validationFailed or not facesContext.postback}"
title="#{clientContext.client.visitor ? messages.disabledForVisitor : tooltip}">
<f:ajax execute="#this" />
</h:commandButton>
I want the commandbutton to cancel the submit when there's an on going ajax happening, so that the validation can finish before the form is submitted, enabling me to prevent users from inputting invalid data and continuing. Is there an easy way to accomplish this?
Cheers

The solution was to change the commandbutton to the primefaces one, and remove the onclick pointing to another commandlink, which executed the backend-logic to traverse to the next page. When I put the action-method in the <p:commandbutton/> the ajax-events were properly queued.

Related

p:commandButton click updates h:form unwantedly

<p:commandButton id="excelAccountLevelOneAccLvl1" ajax="false" icon = "fa fa-fw fa-download" >
<f:param name="accountLevelOneFormRequest" value="accountLevelOneFormRequest" />
<p:dataExporter type="xlsx" target="baselineOneTable"
fileName="#{exportToExcelPageBean.fileName}"
postProcessor="#{exportToExcelPageBean.postProcessXLS}" />
</p:commandButton>
On clicking this button, somehow the forms seems to update and it activates the Faces validation and asks me to fill enter the mandatory field values! I can't figure out why! There is not update parameter here at all!
update is for ajax requests only. You are using ajax="false" which means the commandButton activates a
full page request. That in turn means that the whole form in which the commandButton is included is
processed. If you want to avoid this put your commandButton in a separate form.

Prevent from multiple clicking button in JSF

I want to prevent from multiple clicking button in JSF but every attempt does not work. Action in that button is responsible for loading data to table.
I have something like that:
<h:commandButton class="inputButton bFind" action="#{backingBean.load}" value="#{msgc.find}" />
but that line allows users to click that button even before action ends.
When I try to do something like that:
<a4j:commandButton class="inputButton bFind" onclick="this.disabled=true" oncomplete="this.disabled=false" action="#{backingBean.load}" value="#{msgc.find}" />
or
<a4j:commandButton class="inputButton bFind" onclick="this.disabled=true" oncomplete="this.disabled=false" action="#{backingBean.load}" value="#{msgc.find}" />
then button is blocked and its prevent from multiple clicking but then I must refresh site to see data in table. :/
I have no idea what i should do to this.
Ok i did it. Thx "#Xtreme Biker" for help. All what I need to do is add reRender attribute:
<a4j:commandButton class="inputButton bFind" onclick="this.disabled=true" oncomplete="this.disabled=false" action="#{backingBean.load}" reRender="dataTable_#{backingBean.id}" value="#{msgc.find}" />
and put content which should be rerendered to
<a4j:outputPanel id="dataTable_#{backingBean.id}" ajaxRendered="true">
</a4j:outputPanel>

jsf inputtext to bean

In my JSF Application, I have a page with several inputtext components. When the page is displayed, those inputtext components are populated with data from the database. When I hit the submit button, I want to pass those values as parameters to the next facelet.
What is happening is when I hit Submit, the old values are being passed, and not the updated values that the user has typed in. Here is what one of the inputtext components looks like:
<div align="center">
<h:outputLabel value="Product Quantity " />
<h:inputText id="quantity" value="#{product.quantity}" />
</div>
Then, in the submit button I am trying to get the values that the user types in:
<h:button value="Save Edits" outcome="welcome">
<f:param name="quantity" value="#{product.quantity}" />
</h:button>
Let's say that 100 was the original quantity that the field was populated with. When the user changes it to 110, and hits submit, the welcome facelet still thinks 100 is the value. Any ideas?
Is there any particular reason you've decided to use a <h:button/> instead of an <h:commandButton/>? Because that's the reason why your parameters are not making it to the next page
<h:commandButton/> processes it's enclosing <h:form/>, submitting it's content to the server in a POST request (and the JSF processing lifecycle kicks in e.t.c.) while the <h:button/> will generate a GET request. <h:button/> is generally used for navigation. Stick to <h:commandButton/> if you want to do more than navigate

PrimeFaces :: display p:Dialog to fill-in a form field, without reposting

I have a data-entry form that displays a number of fields (mostly p:inputText) for the user to provide. Some of these are LOVs so I display a p:dialog to allow the user to select the right value. The p:dialog is displayed by means of a p:commandLink next to the p:inputText. Main parts of code shown below:
<h:form id="parentForm">
(...)
<p:inputText value="#{CustomerCEVController.customer.municipality}" id="customerMncName"/>
<p:commandLink type="button" onclick="MunicipalityDlg.show()" styleClass="ui-icon ui-icon-search"/>
(...)
<p:commandButton value="Submit" id="save" actionListener="#{CustomerCEVController.saveButtonListener}" /> (...)
</h:form>
The problem is, whenever the user clicks on the p:commandLink to display the p:dialog (to allow him to select one of the values) the outer form goes through its lifecycle phases (restore view, apply request values, process validations, etc.) since the p:commandLink is placed inside an h:form. How can I implement this dialog-displaying functionality while avoiding posting the h:form with every dialog that the user opens?
Just add "return false" as the last statement to onclick event handler. It prevents commandLink's default function (posting the form).
Just add set the appendToBody attribute to true on <p:dialog>
<p:dialog header="Header Text" widgetVar="dlg" appendToBody="true">
//Content
</p:dialog>
This appends the dialog as a child of the document body outside the parent form.

Restrict f:validator on a specific submit button alone

I'm having a JSF form in which I have a textarea and multiple buttons.
For the text area I'm doing validation using f:validator
<f:validator validatorId="myValidator" />
<a4j:support event="onsubmit" ajaxSingle="true" process="textarea1" />
The validator is working as expected. Now i have multiple submit buttons on the page i want the validation to happen on specific button only and validator should be ignored on the remaining buttons.
Is there anyway to restrict the validator on a specific submit button alone. Thanks.
You can use the disabled attribute.
<f:validator validatorId="myValidator" disabled="#{empty param['formId:buttonId']}" />
Where formId is the ID of your <h:form> and the buttonId is the ID of the button which is supposed to be the only button to trigger validation.
I assume that you want to submit the textarea value to the server when clicking on other buttons too (so no point of playing with the process attribute)
How about adding immediate="true" to the other buttons ?
That way they will skip validation, while the submit button without immediate="true" will do the validation as expected
Or
There seems another workaround in this article JSF 2 - Conditionally Skip Validation
Something like
<h:commandButton action="#{bean.someMethod"} value="Submit2">
<f:param name="skipValidation" value="true"/>
</h:commandButton>
and inside the validate method of the validator check for the skipValidation attirbute (look for further explanation in the article...)

Resources