Prevent confirmation dialogue from opening when there's a validation error - validation

I have a text area inside a tab of accordion panel which is a description. I am trying to edit a description and saving it. I am validating the text area so that max character shouldn't exceed 1000 character. I am using <p:message> to display validation message. Before the actual save, a confirmation dialogue will be shown to confirm the save.
<p:messages showDetail="true" autoUpdate="true" />
<p:accordionPanel dynamic="true">
<p:tab id="_0" title="description">
<p:inputTextarea styleClass="max" id="editDesc1" widgetVar="txtBox" value="#{testBean.description}"
rows="6" cols="150" validatorMessage="#{msg.AddSystem_validationMsg5}" autoResize="false">
<f:validateLength maximum="1000"></f:validateLength>
</p:inputTextarea>
<p:commandButton value="save" oncomplete="saveDialog.show()"/>
<p:confirmDialog message="#{msg.EditSystem_confirmMsg1}" width="200"
showEffect="explode" hideEffect="explode"
header="Confirm" severity="alert" widgetVar="saveDialog">
<p:commandButton value="#{msg.EditSystem_confirmAnswer1}" action="#{testBean.saveEdit}" process="#this" />
<p:commandButton value="#{msg.EditSystem_confirmAnswer2}" onclick="saveDialog.hide()" type="button" />
If an user enters more than 1000 characters and tries to save it, then the validation message appears for a short time and then the confirmation dialogue pops up, causing the validation message to disappear. How do I prevent the confirmation dialogue from popping up when there is a validation error?

You need to check in oncomplete of the save button if validation hasn't failed. PrimeFaces puts a global args object in the JavaScript scope which in turn has a boolean validationFailed property. You could make use of it:
<p:commandButton value="save" oncomplete="if (args && !args.validationFailed) saveDialog.show()"/>
This way the confirm dialog will only be shown if the validation has not failed.

I think you can use javascript to validate:
<script type="text/javascript">
function test(){
// validation here
if(isValidated){saveDialog.show()}
else alert('exceed ...');
}
</script>
<p:commandButton value="save" onclick="test()"/>

Related

Failed validation should prevent closing of modal dialog

I am using Bootsfaces for displaying a modal dialog. Inside the modal dialog there is a field (actually it's b:inputTextarea) and a command button which uses Ajax to submit the data. I want to make sure that the user has entered something to the text field before submitting. If the field is empty then the modal should not be closed and the submit should not happen, if the field is non-empty then the dialog should be closed and the submitting should happen Ajax-style.
Due to an issue with Bootsfaces 1.4.2 I cannot use b:command to do the Ajax-part. I have to use the standard way with h:commandButton and f:ajax.
I am trying to solve my problem like this:
<b:form>
<!-- section that gets updated by ajax-request -->
<b:panel id="updateSection">
<h:outputText value="#{testBean.value1}" />
<b:button value="open dialog" onclick="$('.pseudoClass').modal()" />
</b:panel>
<!-- modal dialog -->
<b:modal title="model" styleClass="pseudoClass" closable="false" closeOnEscape="true">
<b:panel id="modalOutput"><h:inputText value="#{testBean.value1}" /></b:panel>
<f:facet name="footer">
<!-- cancel button -->
<b:button largeScreen="half" value="cancel" dismiss="modal" onclick="return false;" />
<!-- submit button ajax-style -->
<h:commandButton value="submit" action="#{testBean.save()}" onclick="validateModalDialog();">
<f:ajax render="updateSection" execute="#this modalOutput" onevent="closeModalDialog" />
</h:commandButton>
<!-- scripts to close & validate modal dialog -->
<h:outputScript>
function closeModalDialog(data) {
var status = data.status;
if (status === 'complete') { $('.pseudoClass').modal('hide'); }
}
function validateModalDialog() {
alert('i get called before closing dialog');
return false;
}
</h:outputScript>
</f:facet>
</b:modal>
</b:form>
The script function validateModalDialog gets called before the modal dialog gets closed but the dialog gets closed regardless of the return value of the function (true or false).
My knowledge of JavaScript is rather limited. That was one of the reasons I chose to use JSF and Bootsfaces. But I am pretty sure there is a way to do a validation and prevent the dialog from getting closed.
How do I emulate the Bootsfaces functionality (client-side validation of text field in a modal dialog) when using the standard components h:commandButton and f:ajax?
SOLUTION:
To achieve client-side validation preventing the Ajax request from firing and the modal dialog from closing the following change needs to be done compared to my initial code:
<h:commandButton value="submit" action="#{testBean.save()}" onclick="return validateModalDialog();">
<f:ajax render="updateSection" execute="#this modalOutput" onevent="closeModalDialog" />
</h:commandButton>
It indeed looks like
<h:commandButton>
<f:ajax onevent="function(e){if(e.status == 'complete') doSomething();}"/>
</h:commandButton>
is not the equivalent for
<b:commandButton ajax="true" oncomplete="doSomething();"/>
In order to close the modal dialog via javascript from a h:commandButton only if the form has no validation error you have to:
Add the <b:fetchBeanInfos/> component to your form as suggested in this post I originally proposed as duplicate of your question. Also make sure it is updated with each ajax request.
Do not check for data.status == 'complete' but instead data.status == 'success'
Remove the onclick="validateModalDialog();" entirely.
Here is your code changed for server side validation closing the dialog only if the input is not empty (required="true"). Note that also testBean.save() gets invoked only for valid input.
<b:form>
<!-- section that gets updated by ajax-request -->
<b:panel id="updateSection">
<h:outputText value="#{testBean.value1}" />
<b:button value="open dialog" onclick="$('.pseudoClass').modal()" />
</b:panel>
<!-- modal dialog -->
<b:modal title="model" styleClass="pseudoClass" closable="false"
closeOnEscape="true">
<b:panel id="modalOutput">
<h:inputText id="myInput" value="#{testBean.value1}" required="true" />
<h:message for="myInput" />
<b:fetchBeanInfos /> <!-- creates the validationFailed JavaScript variable
and must be within rendered components. -->
</b:panel>
<f:facet name="footer">
<!-- cancel button -->
<b:button largeScreen="half" value="cancel" dismiss="modal"
onclick="return false;" />
<!-- submit button ajax-style -->
<h:commandButton value="submit" action="#{testBean.save()}">
<f:ajax render="updateSection modalOutput"
execute="#this modalOutput" onevent="closeModalDialog" />
</h:commandButton>
<!-- scripts to close & validate modal dialog -->
<h:outputScript>
function closeModalDialog(data) {
var status = data.status;
if (!validationFailed && status === 'success') { $('.pseudoClass').modal('hide'); }
}
</h:outputScript>
</f:facet>
</b:modal>
</b:form>
A little demonstration:
If you want to completely block the ajax form submission on invalid form and do client side validation, you have to modify your onclick in accordance to: JSF ajax request is not fired when combined with JS client-side validation:
<h:commandButton value="submit" action="#{testBean.save()}"
onclick="if(!validateModalDialog()) return false;">
<f:ajax render="updateSection" execute="#this modalOutput" onevent="closeModalDialog" />
</h:commandButton>
Beware client side validation does not prevent users from submitting invalid data by e.g. simply playing around using their browser dev tools.

Validation errors in dialog not updating after failed submit in JSF

So I click a button which opens a dialog. Inside this dialog I want to fill out information in a form and submit and save it. Some of the inputTexts need to be required in order to submit. So I use the required="true" attribute. It stops the submission, but it does not update the field with a red outline of everything. Now, if I hit cancel and open up the dialog again it will show the fields that failed validation with a red outline!
I thought I could solve this by manually updating the dialog whenever I try to submit the form. This just causes the dialog to close though instead of staying open and refreshing the dialog to show the validation failures.
This is the dialog, when I hit the save button is when I submit the form
<h:form>
<p:dialog header="#{headerValue}" widgetVar="#{uniqueId}_editDialog"
modal="false" showEffect="fade" styleClass="dialogGrid"
dynamic="true" draggable="true" resizable="false">
<p:outputPanel style="text-align:center;" layout="block">
<p:messages autoUpdate="true"/>
<ui:insert name="editContent">
Edit Content Here. Use 'selectedModel.whatever'
</ui:insert>
<p:panelGrid columns="3" styleClass="buttonGrid">
<ui:insert name="saveButton">
<p:commandButton iconPos="left" value="#{msg.save}"
rendered="#{'VIEW' != selectedModel.viewState}"
process="#widgetVar(#{uniqueId}_editDialog)"
action="#{adapterInjector.add(modelList, selectedModel)}"
update="#widgetVar(#{uniqueId}_itemsDataList) #widgetVar(#{uniqueId}_addButton) #widgetVar(#{uniqueId}_editDialog)"
oncomplete="if(!args.validationFailed) PF('#{uniqueId}_editDialog').hide()"
partialSubmit="true" validateClient="true">
</p:commandButton>
</ui:insert>
<p:commandButton iconPos="right" value="#{msg.cancel}"
process="#this" oncomplete="PF('#{uniqueId}_editDialog').hide()"
resetValues="true" partialSubmit="true">
</p:commandButton>
</p:panelGrid>
</p:outputPanel>
</p:dialog>
</h:form>
This is an inserted component which has the required attribute
<p:selectOneMenu id="licenseCert"
value="#{selectedModel.selectedLicenseCert}" filter="true"
required="true">
<f:selectItem itemLabel="#{msg.selectOne}" itemValue=""
noSelectionOption="true" />
<f:selectItems value="#{licCert.allLicenseCertMap.entrySet()}"
var="entry" itemValue="#{entry.key}" itemLabel="#{entry.value}" />
</p:selectOneMenu>
</p:column>
Turns out this fixed the problem.
For best practice you should:
move the <h:form> inside the dialog
process the moved <h:form> in the save button.

p:ajax update not working after clicking commandlink

I have a jsf page that adds an order from a client.
All works fine except when I click the commandLink to show the p:dialog to add a new client the update on the "reste" inputtext stop working (even if I close the p:dialog without adding the new client) :
Clients List :
<strong>Client :</strong><
<p:autoComplete
id="client"
value="#{venteSolaireBean.client}"
completeMethod="#{venteSolaireBean.autocompleteClient}"
var="item"
itemLabel="#{item.nom} #{item.prenom}"
itemValue="#{item}"
converter="#{venteSolaireBean.clientConverter}"
dropdown="true"
scrollHeight="200" >
</p:autoComplete>
Link to a p:dialog to add a new Cleint :
<p:commandLink onclick="dlgClient.show()" immediate="true">
<img src="images-main/add-icon.gif" border="0" alt="Add Client" class="img-action"/>
</p:commandLink>
Three p:inputtext items with ajax behavior :
<strong>Montant :</strong>
<p:inputText value="#{venteSolaireBean.venteSolaire.montant}">
<p:ajax event="keyup" update="reste" listener="#{venteSolaireBean.calcul}" />
</p:inputText>
<strong>Avance :</strong></td>
<p:inputText value="#{venteSolaireBean.venteSolaire.avance}">
<p:ajax event="keyup" update="reste" listener="#{venteSolaireBean.calcul}" />
</p:inputText>
<strong>Reste :</strong></td>
<p:inputText id="reste" value="#{venteSolaireBean.venteSolaire.reste}">
</p:inputText>
The venteSolaireBean.calcul function to execute with the listener :
public void calcul() {
venteSolaire.setReste(venteSolaire.getMontant() - venteSolaire.getAvance());
}
I checked by logging the calcul() function and I'm sure it was invoked and the value giving to setReste() is correct.
I don't see why inputtext didn't update.
please help.
I think that there are some problems with the validation. As immediate=true often leads to such problems and you are not using any primefaces-functionality on the button to show the dialog, you should replace the p:commandButton with a plain HTML button to show the "add client"-dialog.

Refresh a form skipping validation when press a button for close: jsf+richfaces

I am using JSF and richfaces. And I am new.
I am looking for information about reset a form in a popup after close it, I do not need to validate the form neither render it. I want to close it and then when I open it again I want the form to be clean.
I have looked information about this, however I do not find the answer to my case. What I have is :
<rich:popupPanel ....
<a4j:outputPanel id="editPaneRegion">
<h:form id="form2EditPane">
<h:panelGrid columns="2" id="edit" ...>
<rich:validator>
<h:outputLabel for="nameContact" value="... " />
<h:panelGrid>
<h:inputText id="nameVontact" value="xbean.selected.name" label="..." required="true" size="20" tabindex="1">
<f:validator validatorId="personNameValidator" />
</h:inputText>
<rich:message for="nameContact" ajaxRendered="true"/>
</h:panelGrid>
</rich:validator>
</h:panelGrid>
....
<a4j:commandButton id="update" value="..." action="#{xBean.edit}" render="form1EditPane:tableContacts, form1EditPane:contactSelect" execute="editPaneRegion" tabindex="6"/>
...
<a4j:commandButton id="close" value="..." oncomplete="#{rich:component('editPane')}.hide();return false;" execute="#this" ajaxSingle="true" immediate="true" tabindex="7"/>
The close button does not works as should be. If I oppen the popup, edit the inputtext and then I close the popup, when I oppen the popup again, it is edited the inputtext, however I want the original as it should be without the edition.
I have found the same question but anything solves my case : I have tried, using a4j:region, different combination of attributes for the button: inmediate= true, action={...clean}, ajaxSimple=true, .. however it doesn't work.
Have someone a solution for this case, I think I miss something obvious as this behaviour should be a common thing, though.
You just need to rerender the form. Whatever you use to make the popup appear make it render the popup as well:
<a4j:commandLink …
render="popupPanel" oncomplete="#{rich:component('popupPanel')}.show();" />
And do not nest forms, you don't have to wrap inputboxes into a <form> like you do in HTML.

AjaxStatus not working with dialog

I have a ajaxstatus and dialog which is used for searching
<h:body>
<p:ajaxStatus onstart="statusDialog.show();" onsuccess="statusDialog.hide();"/>
<p:dialog id="loading" modal="true" widgetVar="statusDialog" header="" draggable="false" closable="false">
<p:graphicImage value="/images/ajax-loader.gif" />
</p:dialog>
Dialog Part
<p:dialog id="showDial" header="Search" widgetVar="srch" resizable="false" >
<h:panelGrid id="searchGrid" columns="2" cellpadding="10" >
<h:outputLabel id="srchIdLbl" value="Employee ID:" />
<p:inputText id="srchIdTxt" value="#{employee.employeeId}" />
<p:commandButton id="search1" value="Search" type="submit" action ="#{employee.search()}"
update="patientTbl"/>
<p:commandButton id="reset1" value="Reset" type="reset" />
</h:panelGrid>
</p:dialog>
the above code works fine, it displays the loading dialog. But once the search is completed the dialog will remain in the screen.
I added the below code in the commandButton id="search1" to close the dialog
onComplete="showDialog.hide()"
*Problem:*If i add the above line the AjaxStatus is not shown. I want to know why its not displaying.
I also tried adding the below code to the commandButton id="search1"
onclick="statusDialog.show()" onselect="statusDialog.show()" onmousedown="statusDialog.show()" onComplete="showDialog.hide() statusDialog.hide()"
Problem In the above code the background to dialog is disabled until the ManagedBeans code is completed and the dialog also closes but when i click the search button it loads with the previously entered search parameter even on clicking the reset button the data doesn't go.
How do i overcome the above problem of the previously entered data not going or how can i do the Ajaxstatus in a better way to avoid the above problems.

Resources