Keep p:dialog open when validation failed - jsf

I have a simple page with data table. Above the table theres a button to add a new table row. This button opens up a pop up form with the registration form. The object which is being created in that form has a bean validation set. Now when I submit an invalid form, the data is not added, a message is created and the pop up window is closed.
My problem is that I want to keep the pop up window open in case the validation is not passed.
The pop up window code:
<p:dialog header="New company registration" widgetVar="cmpRegDialog" modal="true" showEffect="fade" hideEffect="fade" resizable="false">
<p:outputPanel id="cmpRegistration" style="text-align:center;">
<h:panelGrid id="cmpRegistrationGrid" columns="3" columnClasses="label,value" cellpadding="5">
<p:outputLabel for="cmpNameR" value="Name:"/>
<p:inputText id="cmpNameR" value="#{companyBean.newCompany.name}" />
<p:message for="cmpNameR" />
<p:outputLabel for="cmpAddressR" value="Address:"/>
<p:inputText id="cmpAddressR" value="#{companyBean.newCompany.address}" />
<p:message for="cmpAddressR" />
<p:outputLabel for="cmpIcoR" value="ICO:"/>
<p:inputText id="cmpIcoR" value="#{companyBean.newCompany.ico}" />
<p:message for="cmpIcoR" />
<p:commandButton value="Submit" styleClass="secondary-btn flat" action="#{companyBean.registerNewCompany()}" update=":companyRegistrationForm :companiesOverviewForm"/>
<p:commandButton value="Reset" update="cmpRegistrationGrid" process="#this" style="margin-right:10px; width: auto;" styleClass="indigo-btn" >
<p:resetInput target="cmpRegistrationGrid" />
</p:commandButton>
</h:panelGrid>
</p:outputPanel>
</p:dialog>

Yep just add this to your "Submit" button oncomplete="if (!args.validationFailed) PF('#cmpRegDialog').hide();"
<p:commandButton value="Submit"
styleClass="secondary-btn flat"
action="#{companyBean.registerNewCompany()}"
update=":cmpRegistration :companiesOverviewForm"/>
oncomplete="if (!args.validationFailed) PF('#cmpRegDialog').hide();"
Basically only close the dialog if there was no validation failure. NOTE: Make sure not to update="" the form enclosing the dialog or else your dialog will close every time. You should only update the panel inside the dialog "cmpRegistration" like I have done above.

Related

InputTextarea in Dialog shouldn't process but it does

I have an inputTextArea in a dialog and wanted that the bean property shouldn't be sent/changed when the user clicks on the cancel button, but it does.
<p:dialog header="Notizen" id="paketNotizenDialog" modal="true"
widgetVar="paketNotizenDialogWV">
<h:form>
<p:panelGrid columns="1">
<p:inputTextarea scrollHeight="200" rows="6" cols="33" autoResize="false"
value="#{paketErstellenDialogController.selectedPaket.notiz}" />
</p:panelGrid>
<p:commandButton value="Save" process="#form" oncomplete="PF('paketNotizenDialogWV').hide();"/>
<p:commandButton value="Cancel" oncomplete="PF('paketNotizenDialogWV').hide();" process="#none" update="#none" />
</h:form>
</p:dialog>
The button which opens the dialog:
<p:commandButton id="notizEintragButton" value="T" process="#this"
onclick="PF('paketNotizenDialogWV').show();" />
Any hints? Thanks in advance.
As you are using the commandButton, the default behaviour would be to submit the enclosing form with ajax request.
I suspect what you want to do here is to reset the form input and close the dialog. In that case you should go for the type="reset" which according to the primefaces doc:
Reset buttons do not submit the form, just resets the form contents.
And once that is done, trigger your closing javascript code:
<p:commandButton value="Cancel" type="reset"
onclick="PF('paketNotizenDialogWV').hide();"/>
If you do not want to reset the form, just close the dialog then use:
<p:commandButton value="Cancel" type="button"
onclick="PF('paketNotizenDialogWV').hide();"/>
Which according to the primefaces doc would:
Push buttons are used to execute custom javascript without causing an
ajax/non-ajax request. To create a push button set type as "button"
Update
If you want to reset the values from the backing bean then use reset input fields functionality of primefaces.
In your case it would be something like:
<p:panelGrid columns="1">
<p:inputTextarea id="input" scrollHeight="200" rows="6" cols="33" autoResize="false"
value="#{paketErstellenDialogController.selectedPaket.notiz}" />
</p:panelGrid>
<p:commandButton value="Cancel" oncomplete="PF('paketNotizenDialogWV').hide();"
process="#this" update="input" >
<p:resetInput target="input" />
</p:commandButton>
just add type="button" and remove process="#none" update="#none"
from <p:commandButton value="Cancel" oncomplete="PF('paketNotizenDialogWV').hide();" process="#none" update="#none" />

How to change the state of properties before event calls?

I am using this dialog to display a Create form
<p:dialog id="dialogoGestion" header="Asignar nueva gestión" widgetVar="dlg1" >
<p:ajax event="close" update="dialogoGestion"/>
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Cliente: "/>
<h:outputText value="#{miscMB.factura.cliente.nombre}"/>
<h:outputText value="Factura: "/>
<h:outputText value="#{miscMB.factura}"/>
<h:outputLabel value="#{bundle.CreateGestionLabel_descripcion}" for="descripcion" />
<p:inputText id="descripcion" value="#{miscMB.nuevaGestion.descripcion}" title="#{bundle.CreateGestionTitle_descripcion}" />
<h:outputLabel value="#{bundle.CreateGestionLabel_fechaLimiteGestion}" for="fechaLimiteGestion" />
<p:calendar locale="es" pattern="dd/MM/yyyy" id="fechaLimiteGestion" value="#{miscMB.nuevaGestion.fechaLimiteGestion}" title="#{bundle.CreateGestionTitle_fechaLimiteGestion}" required="true" requiredMessage="#{bundle.CreateGestionRequiredMessage_fechaLimiteGestion}">
</p:calendar>
<h:outputLabel value="#{bundle.CreateGestionLabel_usuario}" for="usuario" />
<p:selectOneMenu id="usuario" value="#{miscMB.nuevaGestion.usuario}" required="true" requiredMessage="#{bundle.CreateGestionRequiredMessage_usuario}">
<f:selectItems value="#{usuarioController.itemsAvailableSelectOne}"/>
</p:selectOneMenu>
</h:panelGrid>
<br />
<p:commandButton onsuccess="micalendario.update();PF('dlg1').hide();" action="#{gestionController.crearGestion()}" value="#{bundle.CreateGestionSaveLink}" >
<f:setPropertyActionListener target="#{gestionController.selected}" value="#{miscMB.nuevaGestion}"/>
<f:setPropertyActionListener target="#{gestionController.factura}" value="#{miscMB.factura}"/>
<f:setPropertyActionListener value="#{null}" target="#{miscMB.nuevaGestion}"/>
<f:actionListener binding="#{miscMB.anularNuevaGestion()}"/>
<f:actionListener binding="#{miscMB.agregarGestion(gestionController.selected)}"/>
</p:commandButton>
</h:form>
</p:dialog>
This is where I call the dialog to display
<p:commandLink value="Asignar gestión" onclick="PF('dlg1').show();return false;" action="#{gestionController.preparar()}" rendered="#{miscMB.factura!=null}">
<f:setPropertyActionListener target="#{gestionController.factura}" value="#{miscMB.factura}"/>
</p:commandLink>
What happens is that both <h:outputText value="#{miscMB.factura.cliente.nombre}"/> and <h:outputText value="#{miscMB.factura}"/> values display the properties' last state.
For example, the first time an item selected and you call the dialog, the output is none, because the state is not set. Then, when you select another item and call the dialog, the output is the state last set, which is the previous item value.
Apparently, the setPropertyActionListener in the commandLink is called after the dialog is closed or it executes an action, but not when the commandLink is clicked.
So, how can I set the properties before the dialog frame is displayed?

Simple pop-up after p:selectBooleanCheckbox?

I have several pages where I am using PrimeFaces checkbox in this way:
<p:column>
<f:facet name="header">
<p:selectBooleanCheckbox value="#{Bean.allChecked}">
<p:ajax process="#this" update=":form:table" listener="#{Bean.handleAllChecked}"/>
</p:selectBooleanCheckbox>
</f:facet>
...
</p:column>
I'd like to bring up an info pop-up dialog saying "This will select all items!" with only one "OK" button. How would I do that?
Have in mind that there are several pages with the same behaviour, and I'd like to avoid copy/pasting the same code over and over again if possible.
This can be achived by using primefaces commandButton and Confirmation dialog
in your xhtml file
<f:facet name="header">
<p:commandButton value="Select All" actionListener="#{testBean.handleAll}">
<p:confirm header="Select All" message="This will select all items?"
icon="ui-icon-alert" />
</p:commandButton>
</f:facet>
Add confirmation dialog code (you can create one file and just include in any xhtml )
<p:confirmDialog global="true" showEffect="fade" hideEffect="explode">
<p:commandButton value="Yes" type="button"
styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button"
styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
</p:confirmDialog>
Managedbean
public void handleAll(ActionEvent event){
System.out.println("called only when selected yes");
}
The method handleAll will only be called if user clicks "Yes" otherwise it won't do anything.
I hope that help

How to update component on clientside in primefaces?

I want to create add children button with dialog form feature.
On the page there are tree and modal dialog form. On every node of tree will be the create child button. If you click on create child button, there will be shown modal form, where parentId will be set as id of node where button was clicked
Tree:
<h:form id="TestGroupListForm">
<p:tree value="#{testTreeController.root}" var="node" dynamic="true" cache="false"
selectionMode="single" selection="#{treeBean.selectedNode}" id="tree">
<p:treeNode>
<h:outputText value="#{node.getName()}" /> <p:commandButton id="createButton#{node.getIdTestGroup()}" icon="ui-icon-plus" value="#{bundle.Create}" update="tree" oncomplete="TestGroupCreateDialog.show()"/>
</p:treeNode>
</p:tree>
</h:form>
Dialog Box:
<h:form id="TestGroupCreateForm">
<h:panelGroup id="display">
<p:panelGrid columns="2" >
<p:outputLabel value="#{bundle.CreateTestGroupLabel_name}" for="name" />
<p:inputText id="name" value="#{testGroupController.selected.name}" title="#{bundle.CreateTestGroupTitle_name}" />
<h:inputHidden id="parentId" value="#{testGroupController.selected.parentId}" />
</p:panelGrid>
<p:commandButton actionListener="#{testGroupController.saveNew}" value="#{bundle.Save}" update="display,:TestGroupListForm:tree,:growl" oncomplete="handleSubmit(xhr,status,args,TestGroupCreateDialog);"/>
<p:commandButton value="#{bundle.Cancel}" onclick="TestGroupCreateDialog.hide()"/>
</h:panelGroup>
</h:form>
</p:dialog>
I want that click on
<p:commandButton id="createButton#{node.getIdTestGroup()}" icon="ui-icon-plus" value="#{bundle.Create}" update="tree" oncomplete="TestGroupCreateDialog.show()"/>
Will set value of:
<h:inputHidden id="parentId" value="#{testGroupController.selected.parentId}" />
UPDATE
I have to use action listener testGroupController.nodeListener to set parentId of the new item.
<p:commandButton process="#this" id="createButton" actionListener="#{testGroupController.nodeListener}" icon="ui-icon-plus" value="#{bundle.CreateGroup}" update=":TestGroupCreateForm" oncomplete="TestGroupCreateDialog.show()">
<f:attribute name="rawParentId" value="#{node.getIdTestGroup()}" />
</p:commandButton>
You can add parentId to the existing update= attribute like so:
update="tree parentId"
This will render parentId and set its value to testGroupController.selected.parentId.
Edit
You can process any values from the UI to the been too, by using:
process="myInputId"
Example
<h:form>
<h:inputText id="input"
value="#{bean.value}" />
<h:outputText id="output"
value="#{bean.value}" />
<p:commandButton process="input"
update="output"
value="Submit" />
Upon clicking your button, the value of id="input" will be set in bean.value (as ordered by process="input"). Next your id="output" will be rendered (or updated) with bean.value (as ordered by update="output").

How to only show dialog after successfully validated text field

So I have form with 1 fields that need to be required
<h:form id="form">
<h:panelGrid columns="2">
<h:inputText id="default" requiredMessage="This field is required."
value="#{displayName.name}" required="true" />
<p:message for="default"/>
</h:panelGrid>
<p:commandButton value="Test" update="form" onclick="displayDlg.show();"/>
</h:form>
<p:dialog header="Dialog" widgetVar="displayDlg" id="dialog">
<h:outputText value="The name you just input is: #{displayName.name}"/>
</p:dialog>
So when I click button Test, and not having anything inside the text-box, then an error message pop out.
I want that if the validation process success, then I want to display a dialog box that display name that you just type in. But if validation fail, then dont diplay the dialog. And I have a hard time making this happen. I try to put the dialog inside or outside the dialog, but no work. Please give me some advice
You could make use of the visible attribute of <p:dialog> and ajax-update the whole dialog.
<h:form id="form">
<h:panelGrid columns="2">
<h:inputText id="default" requiredMessage="This field is required."
value="#{displayName.name}" required="true" />
<p:message for="default"/>
</h:panelGrid>
<p:commandButton value="Test" update="form :dialog" />
</h:form>
<p:dialog id="dialog" header="Dialog" visible="#{not empty displayName.name}">
<h:outputText value="The name you just input is: #{displayName.name}"/>
</p:dialog>
Additional benefit of having :dialog in the update is that it will update the entered name as well everytime you change it.

Resources