I have a form inside the p:dialog component that is submitted via AJAX. The form in the dialog box via ui:include another .xhtml containing only the form and its components (no, I'm not nested forms, the dialog box itself is not included in any form). The bean page included is "ViewScoped."
MOST functions work fine:
- Upon successful validation, the form will execute the save method; after successful saving, the dialog closes; opening a subsequent record shows the correct information about the record from the database.
- If the validation fails, the transferred values ββare saved, and the dialog remains open and displays validation errors, correcting invalid fields and retrieving the results in a successful save.
The problem occurs when the action failed caused by p:commandButton . In the event of a failure, the dialog remains open and displays "Error saving changes" via h:messages for the user; in addition, the values ββpresented are still stored in the input fields. This is fine (and even desirable) as long as the form remains open, however - after closing the dialog and reopening, the presented STILL values ββin the text fields. This is bad because it gives the user the impression that the save was successful (since the h:messages component is now empty due to updating the dialog).
So far I have tried the following: NONE of which fixed the problem:
- 1.1) Installing the bean support of the included form in a new instance of the open bean dialog.
- 1.2) Since the bean is now a new instance, I also re-populate the address object with data from the bean data.
- 2.1) Disabling the close button in the dialog box and adding the
p:commandButton "Cancel" button using the p:resetInput component to close the / reset form dialog. (the dialog closes, but the values ββsent in the form are saved). - 2.2) A method call from this
p:commandButton , which removes the RequestMap for the included bean support form. - 2.3) I tried with the button set to both
immediate=true and immediate=false . - 2.4) I tried with the button set to
process=@this similar tactic that I used to close the form to make sure that it would have fresh fields to reopen.
You might consider installing a backup bean in a new instance and repeating the address object, I would see a new form, but NOPE.
Here are some of the sources:
Serving mainform.xhtml
<p:dialog id="dlgAddress" header="Address Edit" widgetVar="dialogAddress" dynamic="true" modal="false" closable="false" resizable="false" styleClass="dlgAddress" visible="#{addressform.showDlgAddress}"> <ui:include src="addressform.xhtml"/> </p:dialog>
addressform.xhtml
<h:form id="fDlgAddress"> <div id="addresses-container"> <h:messages id="msgDlgAddress" errorClass="errormsg" infoClass="infomsg1" layout="table"/> <h:panelGrid columns="1" styleClass="pgAddresses" rendered="#{!addressform.address.exists}"> <h:outputText value="No active #{addressform.address.atypCode} address found." styleClass="record-not-exists"/> <h:outputText value="Use the form below to create one."/> </h:panelGrid> <p:panelGrid columns="2" styleClass="pgDlgForm pgAddresses"> <h:outputLabel value="Address Type"/> <h:inputText id="atypCode1" value="#{addressform.address.atypCode}" disabled="true" rendered="#{addressform.address.exists}"/> <h:selectOneMenu id="atypCode2" value="#{addressform.address.atypCode}" rendered="#{!addressform.address.exists}"> <f:selectItems value="#{addressform.atypCodeList}" var="atyp" itemValue="#{atyp}" itemLabel="#{atyp}"/> </h:selectOneMenu> <h:outputLabel value="Street 1" for="street1"/> <h:inputText id="street1" value="#{addressform.address.addressLine1}"/> <h:outputLabel value="Street 2" for="street2"/> <h:inputText id="street2" value="#{addressform.address.addressLine2}"/> <h:outputLabel value="Street 3" for="street3"/> <h:inputText id="street3" value="#{addressform.address.addressLine3}"/> <h:outputLabel value="Street 4" for="street4"/> <h:inputText id="street4" value="#{addressform.address.addressLine4}"/> <h:outputLabel value="City" for="city"/> <h:inputText id="city" value="#{addressform.address.city}" required="true" requiredMessage="Please enter a city."/> <h:outputLabel value="State" for="statCode"/> <h:selectOneMenu id="statCode" value="#{addressform.address.stateCode}"> <f:selectItem itemLabel="Select State/Province" itemValue=""/> <f:selectItems value="#{states.statesList}" var="stat" itemValue="#{stat.statCode}" itemLabel="#{stat.statDesc}"/> </h:selectOneMenu> <h:outputLabel value="Zip Code" for="zipCode"/> <h:inputText id="zipCode" value="#{addressform.address.zip}"/> <h:outputLabel value="Country" for="natnCode"/> <h:selectOneMenu id="natnCode" value="#{addressform.address.nationCode}" required="true" requiredMessage="Please choose a nation."> <f:selectItem itemLabel="Select Country" itemValue=""/> <f:selectItems value="#{nations.nationsList}" var="natn" itemValue="#{natn.natnCode}" itemLabel="#{natn.natnDesc}"/> </h:selectOneMenu> <h:outputLabel value="From Date" for="fromDate"/> <p:calendar id="fromDate" value="#{addressform.address.fromDate}" showButtonPanel="true"/> <h:outputLabel value="To Date" for="toDate"/> <p:calendar id="toDate" value="#{addressform.address.toDate}" showButtonPanel="true"/> <h:outputLabel value="Inactivate" for="inactivateAddress" rendered="#{addressform.address.exists}"/> <h:selectBooleanCheckbox id="inactivateAddress" value="#{addressform.address.inactivate}" rendered="#{addressform.address.exists}"/> <h:outputLabel value="Delete" for="deleteAddress" rendered="#{addressform.address.exists}"/> <h:selectBooleanCheckbox id="deleteAddress" value="#{addressform.address.delete}" rendered="#{addressform.address.exists}"/> </p:panelGrid> </div> <div class="button-container"> <p:commandButton value="Save Changes" action="#{addressform.save}" type="submit" ajax="true" process="@form" update="@form"/> <p:commandButton value="Cancel" process="@this" onclick="dialogAddress.hide();"> <p:resetInput target="fDlgAddress"/> </p:commandButton> </div> </h:form>
Recorddetailsform (bean support for the form from which the address dialog is called)
public void showDlgAddress(){ FacesContext ctx = FacesContext.getCurrentInstance(); ELResolver resolver = ctx.getApplication().getELResolver(); RecordDetails recordDetails = (RecordDetails) resolver.getValue(ctx.getELContext(), null, "recordDetails"); //Set addressform backing bean to new instance and load address into it from recordDetails resolver.setValue(ctx.getELContext(), null, "addressform", new Addressform()); Addressform addressform = (Addressform) resolver.getValue(ctx.getELContext(), null, "addressform"); addressform.setAddress(recordDetails.getAddress()); }
Address form (bean address form support)
public void save() { FacesContext ctx = FacesContext.getCurrentInstance(); RequestContext rctx = RequestContext.getCurrentInstance(); ELResolver resolver = ctx.getApplication().getELResolver(); Records records = (Records) resolver.getValue(ctx.getELContext(), null, "records"); RecordDetails recordDetails = (RecordDetails) resolver.getValue(ctx.getELContext(), null, "recordDetails"); Mainform mainform = (Mainform) resolver.getValue(ctx.getELContext(), null, "mainform"); Person person = (Person) resolver.getValue(ctx.getELContext(), null, "person"); //Pretty lengthy SQL stuff here. Commented out. Just wanted to display the display logic below for the dialog. if (errorMsg != null) {//If errorMsg is not null, then error occurred. showDlgAddress = true;//Ensures address dialog remains open in event of action error. queueErrorMessage(errorMsg); rctx.update("dlgAddress"); return;//break out of method on error. } else { showDlgAddress = false; rctx.update("dlgAddress"); } //If everything saves without error, repopulate address and update recordDetails dialog. recordDetails.populateAddress(records.getSelectedRecord()); mainform.updateDlgRecordDetails(); }
Additional Information:
- Jsf2
- Basic fonts 3.5
- Tomcat 6.0
- Netbeans