I am having a problem with not closing a PrimeFaces dialog. The input field 'username' is required:
<p:outputLabel for="username" value="Username: "/>
<p:inputText id="username"
value="#{employeeController.employee.username}" required="true"/>
I used the following code to prevent the dialog from closing if the field is empty:
<p:commandButton value="Save" action="{employeeController.doSaveEmployee()}"
oncomplete="if (args && !args.validationFailed) PF('employeeAddDialog').hide()"
update=":employeeForm"/>
But the dialog still closes whenever I click on 'Save' no matter if 'username' is filled or not. When I open the dialog again after closing the error message is displayed, so I know that the input validation works.
EDIT:
<p:dialog header="Create Employee" id="employeeAddDialog" widgetVar="employeeAddDialog" modal="true" showEffect="fade" hideEffect="fade" resizable="false">
<p:outputPanel id="employeeDataCreate">
<h:panelGrid columns="2">
<p:outputLabel for="username" value="Username: " />
<p:inputText id="username" value="#{employeeController.employee.username}" required="true" />
<p:outputLabel for="password" value="Password: " />
<p:password id="password" value="#{employeeController.employee.password}" />
</h:panelGrid>
<h:panelGrid columns="3">
<p:commandButton value="Save" action="#{employeeController.doSaveEmployee()}" oncomplete="if (args && !args.validationFailed) PF('employeeAddDialog').hide()" update=":employeeForm" />
<p:commandButton value="Abort" oncomplete="PF('employeeAddDialog').hide()" />
</h:panelGrid>
</p:outputPanel>
</p:dialog>
Here is some more code. What else could be the cause for this problem?
employeeForm is just a dataTable that lists employees with their corresponding attributes.
EDIT2:
This code in EmployeeController yields the wanted behavior, but only if I remove update=":employeeForm" from the 'Save'-button
public void doSaveEmployee() {
employee = employeeService.saveEmployee(employee);
employee = null;
initNewEmployee();
initList();
RequestContext context = RequestContext.getCurrentInstance();
context.execute("PF('employeeAddDialog').hide();");
}
FINAL EDIT:
My dialog was closing because I updated the whole form. Changing update=":employeeForm" to update=":employeeForm:employeeTable" made things work like intended.
not sure why you are using oncomplete="args & amp; & amp; ...". I have never used that and works great.
oncomplete="if (args && !args.validationFailed) PF('employeeAddDialog').hide()"
I use it like:
oncomplete="if (!args.validationFailed) PF('employeeAddDialog').hide()"
is this a question error?
i suggest make close operaction in employeeController.doSaveEmployee() after succes save action
RequestContext context = RequestContext.getCurrentInstance();
context.execute("PF('myDialogVar').hide();");
Related
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.
Suppose having a p:dialog with an <o:validateOne> on submit button where p:dialog will close after that the dialog closes even if the validation is still required
<h:form>
<h:outputText id="newValueId" value="#{myBean.newValue}/>
<p:dialog id="dialog" widgetVar="dlg" resizable="false" dynamic="true"
appendToBody="false" modal="true">
<o:validateOne id="one" components="name1 name2"
message="one is required"/>
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel value="name 1 :" />
<p:inputText value="#{myBean.name1}" id="name1"/>
<h:outputLabel fvalue="name 2 :" />
<p:inputText value="#{myBean.name2}" id="name2"/>
<p:commandLink id="okId" value="ok" update="growl newValueId"
action="#{myBean.updateMyForm}"
process="dialog"
oncomplete="if(!args.validationFailed())dlg.hide();"/>
</h:panelGrid>
</p:dialog>
class Mybean{
String name1,name2,newValue;
public void updateMyForm(){
newValue=name1 + " " + name2;
}
//getter and setters
}
I want the dialog to not close if the two inputs input1 and input2 are still empty
But what what's happening is that dialog is closed and message is the displayed in the growl
I have a view which is working well. However, when I add a required="true" into the body of the view, the view begin to be unable to read backing bean properly. Below is a comparison:
Anyone knows why?
.
Edit: Code fragment supplement
Below is the fragment of my code in which the problem arises. If I add required="true" into any p:inputText (not only the p:inputText that belong to this dialog but any p:inputText inside the html body), it stops displaying information from backing bean, remove it and everything works just fine.
<p:dialog header="Customer Editor" widgetVar="customerEditDialog"
resizable="false" id="customerEditDlg" showEffect="fade"
hideEffect="fade" modal="true">
<h:panelGrid id="editGrid" columns="2" cellpadding="4"
style="margin:0 auto;">
<h:outputLabel for="customerNameEdit" value="Name: " />
<p:inputText id="customerNameEdit" maxlength="30"
value="#{customerController.customerAdd.name}" />
<h:outputLabel for="customerPhoneNumberEdit" value="Phone Number " />
<p:inputText id="customerPhoneNumberEdit" maxlength="15"
onkeypress="if(event.which < 48 || event.which > 57) return false;"
value="#{customerController.customerAdd.phoneNumber}" />
<h:outputLabel for="customerEmailEdit" value="Email: " />
<p:inputText id="customerEmailEdit" maxlength="49"
value="#{customerController.customerAdd.email}" />
<h:outputLabel for="customerAddressEdit" value="Address: " />
<p:inputText id="customerAddressEdit" maxlength="190"
value="#{customerController.customerAdd.address}" />
<f:facet name="footer">
<div style="text-align: right">
<p:commandButton id="editCustomerButton"
update=":form:customerList, :form:messages"
oncomplete="customerEditDialog.hide()" value="Save"
actionListener="#{customerController.editCustomer()}">
</p:commandButton>
<p:commandButton id="cancelEditCustomerButton" update=":form"
onclick="customerEditDialog.hide()" value="Cancel">
</p:commandButton>
</div>
</f:facet>
</h:panelGrid>
</p:dialog>
See if jsf required=true destroys setPropertyActionListener? helps you.
The problem is most likely that the setter in your bean is not to be called because of validation errors somewhere else or you are nesting <h:form> elements.
I have a CRUD page which shows data from a query (a List of domain objects) in a Primefaces datatable.
<p:dataTable
id="negozi"
var="n"
value="#{nController.theListFromQuery}"
rowKey="#{n.id}"
selection="#{nController.selected}"
selectionMode="single">
<p:column headerText="Field1">
<h:outputText value="#{n.f1}" />
</p:column>
<p:column headerText="Field2">
<h:outputText value="#{n.f2}" />
</p:column>
<p:column style="width:4%">
<p:commandButton
actionListener="#{nController.prepareEdit(n)}"
update=":editDialogId"
oncomplete="editDialog.show()"
value="Edit" />
</p:column>
...
By clicking on the edit button a dialog will be shown:
<p:dialog
header="Edit N"
widgetVar="editDialog"
id="editDialogId">
<h:form id="formDialog">
<h:panelGrid id="editDialogTable" columns="2" cellpadding="10" style="margin:0 auto;">
<p:outputLabel for="field1" value="F1:" />
<p:inputText id="field1" value="#{nController.selected.f1}" />
<p:outputLabel for="field2" value="F2:" />
<p:inputText id="field2" value="#{nController.selected.f2}" />
<p:commandButton
value="Confirm"
actionListener="#{nController.doEdit}"
update=":form"
oncomplete="editDialog.hide()"
rendered="#{nController.selected.id!=null}" />
...
It works. Now I want to make F1 a required field.
I add the "required" attribute to the inputText field and what happens?
When I try to confirm the form without the required field, the entity is not edited (that's right) but the dialog is closed (that's NOT right!)
When I reopen the dialog I can see the red highlight on the required (and invalid) field.
What I want is to prevent the dialog closing if the form is invalid.
Do I have to write some JS or will JSF help me?
The PrimeFaces ajax response puts an args object in the scope which has a validationFailed property. You could just make use of it.
oncomplete="if (args && !args.validationFailed) PF('editDialog').hide()"
(the args precheck is necessary to not cause a JS error when an exception is thrown during request)
You could refactor it to a reusable JS function as follows.
oncomplete="hideDialogOnSuccess(args, 'editDialog')"
function hideDialogOnSuccess(args, dialogWidgetVar) {
if (args && !args.validationFailed) {
PF(dialogWidgetVar).hide();
}
}
this post is now three years old, but I have found helpful, so my findings may help others.
In PF 5.x at least, it seems that the solution provided by BalusC has to be modified in two ways. (1) add the "args" argument to the call in oncomplete event hander, and (2) use the PF primefaces primitive to identify the widget in PF tables. Here is the code I am using:
oncomplete="hideDialogOnSuccess(args, PF('editDialog'))"
function hideDialogOnSuccess(args, dialogWidgetVar) {
if (args && !args.validationFailed) {
dialogWidgetVar.hide();
}
}
I believe this is the cleanest solution.
Doing this you don't need to change your buttons code.
This solution overrides the hide function prototype.
$(document).ready(function() {
PrimeFaces.widget.Dialog.prototype.originalHide = PrimeFaces.widget.Dialog.prototype.hide; // keep a reference to the original hide()
PrimeFaces.widget.Dialog.prototype.hide = function() {
var ajaxResponseArgs = arguments.callee.caller.arguments[2]; // accesses oncomplete arguments
if (ajaxResponseArgs && ajaxResponseArgs.validationFailed) {
return; // on validation error, prevent closing
}
this.originalHide();
};
});
This way, you can keep your code like:
<p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();"
actionListener="#{videoBean.saveVideo(video)}" />
to keep the dialog Open on validation Failed, you just need set the commandButton as follows:
<p:commandButton value="save"
action="#{YourBean.yourActionMethod}"
oncomplete="if (!args.validationFailed) PF('yourDialogWidgetVar').hide()"/>
I gonna leave here a complete example:
<h:form id="ad-form">
<p:dialog id="ad-dialog" widgetVar="adDialog" modal="true" width="400"
closeOnEscape="true" resizable="false" header="Addreass">
<p:messages id="a-msgs" closable="true" />
<h:panelGrid columns="2" id="ad-painel-dialog" width="100%">
<p:outputLabel value="Country" for="country" />
<p:inputText id="country" style="width:100%"
value="#{clientSaverBean.editableAddress.country}" />
<p:outputLabel value="City" for="city" />
<p:inputText id="city"
value="#{clientSaverBean.editableAddress.city}" />
<p:outputLabel value="Zip-Code" for="zipcode" />
<p:inputText id="zipcode"
value="#{clientSaverBean.editableAddress.zipCode}" />
<p:outputLabel value="Street" for="street" />
<p:inputTextarea id="street"
value="#{clientSaverBean.editableAddress.street}" />
<p:outputLabel value="Number" for="number" />
<p:inputText id="number"
value="#{clientSaverBean.editableAddress.number}" />
<h:panelGroup />
<f:facet name="footer">
<p:commandButton value="save"
action="#{clientSaverBean.saveAddress}"
process=":ad-form:ad-dialog"
update=":ad-form:a-msgs :ad-form:ad-painel-dialog :client-form:ad-table"
oncomplete="if (!args.validationFailed) PF('adDialog').hide()"/>
</f:facet>
</h:panelGrid>
</p:dialog>
</h:form>
In my previous question I had the problem of displaying validation messages from a Login form. That issue is now solved, but this time I am not able to display a custom message with FacesContex#addMessage.
Using JSF + PrimeFaces.
<p:dialog header="Login" widgetVar="loginDlg">
<h:form id="loginForm">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="username" value="Username:" />
<p:inputText value="#{loginBean.username}" id="username" required="true" label="username" />
<p:message for="username" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret value="#{loginBean.password}" id="password" required="true" label="password" />
<p:message for="password" />
<f:facet name="footer">
<p:commandButton value="Login" id="loginDlgButton" update=":loginForm,:welcomeMsg" actionListener="#{loginBean.login}"
oncomplete="handleLoginRequest(xhr, status, args)"/>
<p:message for="loginDlgButton" />
</f:facet>
</h:panelGrid>
</h:form>
</p:dialog>
In LoginBean (a SessionScoped ManagedBean):
public void login() {
FacesContext context = FacesContext.getCurrentInstance();
RequestContext rContext = RequestContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.login(this.username, this.password);
rContext.addCallbackParam("loggedIn", true);
} catch (ServletException e) {
rContext.addCallbackParam("loggedIn", false);
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", "Invalid credentials"));
}
}
This code, when validation succeeds and login fails, should display the "Invalid credential" message, but doesn't. Moreover, somewhere in the body of my web page, I have also added this line:
<p:messages autoUpdate="true" />
but my message isn't displayed even there.
Javadocs say that
If clientId is null, this FacesMessage is assumed to not be associated with any specific component instance
But I can't understand what this means.
place <p:messages autoUpdate="true" /> inside your form or inside some wrapper that is being updated by update of your commandButton , or place loginDlgButton instead of null in context.addMessage(...
I don't see a p:messages tag in your code. It is not the same as the p:message tag. p:message is attached to another component and is displayed as part of validation. The p:messages (or p:growl) component is what you are updating in your bean. Try adding a messages or growl component like this:
<h:form id="loginForm">
<p:growl id="messageGrowl" showDetail="true" sticky="false" />
<h:panelGrid columns="3" cellpadding="5">