Update Datatable and Messages When Dialog Closes in Primefaces - jsf

I have a relatively simple datatable that contains a list of requests. I have command buttons for approval and rejection and a messages section at top to provide feedback.
For the approvals I simply process everything and refresh the datatable and message but for rejections I want to prompt the user for a message. No matter what I seem to do I cannot have both the datatable update and the message show when the dialog closes. The best I could achieve was for the message to appear for a few milliseconds whilst the dialog was closing.
so my page starts with the messages and a form and a datatable
<h:form id="form">
<p:messages id="messages" showDetail="true" closable="true">
<p:autoUpdate />
</p:messages>
<p:dataTable id="dtReqs" allowUnsorting="true" sortMode="single" value="#{myBean.openRequests}" var="req">
then I have a command button to process the rejections
<p:column headerText="Reject" width="60">
<p:commandButton icon="pi pi-times" styleClass="rounded-button ui-button-danger"
oncomplete="PF('rejectDlg').show()">
<f:setPropertyActionListener value="#{req}" target="#{myBean.selectedRequest}" />
</p:commandButton>
</p:column>
and finally a dialog to get the user input
<p:dialog id="inputDialog" widgetVar="rejectDlg" header="Enter Rejection Explanation" modal="true">         
<p:ajax event="close" update=":form:dtReqs" />
<p>Please enter a reason for rejection</p>
<p:inputTextarea id="rejectReasonText" rows="5" cols="60" value="#{myBean.userMessage}" />
<br /> <br />
<p:commandButton value="Reject" action="#{myBean.processRejection}"
icon="pi pi-times" styleClass="ui-button-danger" />
<p:commandButton value="Cancel" onclick="PF('rejectDlg').hide()" />      
</p:dialog>
the ViewScoped baking bean then has
public void procesRejection() {
//handle updates and update variables
FacesMessage msg = new FacesMessage("Title", "Content");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
With code as is when you click the reject button on the dialog it does all the processing it needs to do (and works fine) and the message is displayed behind the dialog but the form doesn't get closed and the datatable is only updated when you click cancel or the x to close the dialog.
I have tried adding oncomplete on the reject button to close the form and whilst this works and updates the datatable, the message flashes up for a millisecond and then vanished along with the form. I have tried closing the form in the processRejection method which achieves the same result.
Removing the ajax close event and adding oncomplete to the reject button to close the dialog closes the dialog and displays the message but doesn't refresh the datatable.
How can I achieve what I want in prompting the user for some text and then
Close Dialog
Refresh datatable
Display message

Related

How to add confirmation check for a button which is calling a remoteCommand

I have a situation in primefaces, where I have a button which on click calls a remote command through java script as a callback, this remote command is responsible to perform save action. I want to add confirmation to the Save button based on some controller value. So the expected output is on click if that value is true I want to show the confirmation dialog else I just want to do the normal save.
I am really new to primefaces. Any help would be highly appreciated.
<p:remoteCommand name="save" actionListener="#{controller.save()}" oncomplete="PF('statusDialog').hide()"/>
<p:button value="Save" styleClass="btn-primary btn-save" onclick="PF('statusDialog').show(); Modeler.saveBpmnToForm(save)" />
Whenever you trigger the remote command you could redirect the action to show the actual confirm dialog, then from there you can associate the action with the "confirm" button. The following logic is meant to show the dialog only if your boolean variable is true, otherwise you perform the save action without showing any dialog.
<p:remoteCommand name="save" actionListener="#{controller.status ?
controller.showDialog : controller.save}" oncomplete="PF('statusDialog').hide()"/>
Whenever this remoteCommand is triggered you'll show the following dialog using the bean:
<p:dialog id="confirmDialog" >
<p:button value="Confirm" styleClass="btn-primary btn-save"
onclick="PF('statusDialog').show()" action="#{controller.save}"/>
<p:button value="Cancel" styleClass="btn-primary btn-cancel"
onclick="PF('confirmDialog').hide()"/>
</p:dialog>
The "confirm" button will perform the actual logic, the "cancel" should only close the dialog but this is up to you.

Close dialog prior to navigate away from the page

PrimeFaces: 7.0
JSF: 2.2.13
JBoss: 7.1
Java: 1.8
Chrome: 83.0.4103.116
I have a simple confirmation dialog to go to another page, there a reason for the action should be provided as a text.
It boils down to the following lines of code:
<p:dialog id="dlg" widgetVar="dlg" modal="true">
<h:form id="dlgForm">
<p:inputText id="reason" required="true" value="#{bean.reason}"/>
<p:message for="reason"/>
<p:commandButton id="proceed" value="Proceed" update="dlgForm" action="#{bean.action}"/>
<p:commandButton id="cancel" value="Cancel" resetValues="true" onclick="PF('dlg').hide()">
<p:ajax update="dlgForm" resetValues="true"/>
</p:commandButton>
</h:form>
</p:dialog>
And the bean:
#ManagedBean(name = "bean")
#SessionScoped
class Bean {
public String processGrundFuerExportDlg() {
PrimeFaces.current().executeScript("PF('dlg').hide()");
return "other_page";
}
}
My requirements:
Dialog opens with the empty 'reason'-inputText.
If 'cancel' is pressed: dialog should close
If 'proceed' is pressed:
If reason is not empty: close dialog and navigate to the 'other_page'
If return is empty: show the error message and don't close the dialog
My problem with this code: the line
PrimeFaces.current().executeScript("PF('dlg').hide()");
seems to be executed AFTER the current page being left resulting in 'dlg' not being found (JavaScript error).
The not properly closed dialog produces a nasty side effect: After returning to my first page later on, the dialog overlay stays active and inputText elements can't be activated with the mouse (TAB works). Overlay logic in the event loop blocks mouse clicks to from being passed to the components on the page.
My question:
How this standard scenario should be properly implemented with JSF and PrimeFaces?
If Upgrade to other versions is required, are there some workaround for removing stale overlays without upgrading?
Disclaimer: I studied many related questions on StackOverflow and tried all proposed solutions without success. For example this one: Keep p:dialog open when a validation error occurs after submit
You won't be having this problem if you would redirect to the new page instead of triggering an Ajax update.
You can simply add ?faces-redirect=true to your returned string, so:
return "other_page?faces-redirect=true";
Or, if you are using faces-config, add <redirect/> to the <navigation-case>.
Then you can remove the script from your bean where you try to close the dialog.
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
If 'proceed' is pressed:
If reason is not empty: close dialog and navigate to the 'other_page'
If return is empty: show the error message and don't close the dialog.
All this above is handled with required true on reason inputText. If reason is empty action in proceed commandButton won't start.
You don' need to close your dialog before you are navigating to other page.

CommandButton not calling actionListener when I close confirmDialog

I have buttons Stop and Release which call a save method and within the save method a confirmDialog is shown. I can use the Stop button, press OK in the dialog and the method works, but then when I go to clock Release again the button doesn't call the actionListener. Similar for clicking Release, confirming then trying to Stop.
Here are the two command buttons, which sit inside modeControls.
<p:commandButton title="Stop" value="Stop"
rendered="#{unitSetVehicleStatusBean.crudMode == 'READ' and unitSetVehicleStatusBean.stopped =='false'}"
actionListener="#{unitSetVehicleStatusBean.stop}"
update="modeControls :mainForm"
process="#this :mainForm"/>
<p:commandButton title="Release" value="Release"
rendered="#{unitSetVehicleStatusBean.crudMode == 'READ' and unitSetVehicleStatusBean.stopped =='true'}"
actionListener="#{unitSetVehicleStatusBean.release}"
update="modeControls :mainForm"
process="#this :mainForm"/>
Here is the confirmDialog. The save method it calls is called from within the stop() and release() methods, then after some validation I use
RequestContext context = RequestContext
.getCurrentInstance();
context.execute("PF('saveNDTDialog').show();");
break;
and when the user selects OK in the confirmDialog it will rejoin this method part way through a switch statement and complete the save.
Here is the confirmDialog.
<p:confirmDialog id="saveNDTDialog" appendTo="#(body)"
widgetVar="saveNDTDialog" closeOnEscape="true"
closable="true"
message="#{message.stoppedValidationNDTWarning}">
<p:commandButton value="OK"
update="mainForm :modeControls"
actionListener="#{unitSetVehicleStatusBean.save('WARNING_NDT')}"
oncomplete="saveNDTDlg.hide();"/>
<p:commandButton value="Cancel"
onclick="saveNDTDlg.hide();" />
</p:confirmDialog>
I believe the issue is something to do with the appendTo or possibly onComplete, but aren't too sure what's going wrong.
Any suggestions welcome...
By pulling the dialog out of the main form and adding a form around the commandButtons in the dialogs, the dialogs began working as expected.

dialog will not close primefaces

I have a dialog on one of my pages. It opens fine. It works fine if you use the button on the page, it closes. However, if you try and "x" out of the dialog it will not close. I believe it is related to the fact that I have an input field on the dialog, but I am not sure. I apologize if this is a dupe, I could not find a similar post.
<p:commandButton action="#{phoneListBean.debugger}"
value="Merge Unqiue" onclick="mdlg.show();"
update=":pmsg, :createNewPanel, :listform" />
<p:dialog id="mdialog" header="Merge Unqiue" widgetVar="mdlg"
appendToBody="true">
<h:form id="mform">
<h:panelGrid columns="2" cellpadding="5" id="m">
<h:outputLabel for="listName" value="Enter the List Name:" />
<p:inputText value="#{phoneListBean.mergeList.name}" id="listName" />
<p:commandButton action="#{phoneListBean.mergeUnique}"
value="Merge Unqiue" update=":pmsg, :listform"
onclick="mdlg.hide();" />
</h:panelGrid>
</h:form>
</p:dialog>
Thanks in advance for the help.
Your problem is that you don't want to use the onclick attribute with Primefaces buttons for displaying and hiding the dialogs. The click event may not get invoked before the postback because these buttons are not Ajax enabled.
Instead you should use oncomplete attribute. This will notify the Javascript event to execute only after the server postback has occurred, meaning that show() will display already updated dialog contents, and hide() will occur only after the server side execution has finished.

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.

Resources