using jsf primefaces button closing a dialog depending on a boolean at oncomplete event - jsf

I have a problem. I have a JSF Primefaces environment, and I would like to set the password. In the bean there is a method, it can throw exception or set the doneChange boolean to true.
I want the following run:
If the doneChange boolean is true, just close the dialog where the button is, and open an another.
Here is the code of the button:
<p:commandButton id="changeButtonId"
type="submit"
value="#{msg.changePassword}"
ajax="true"
action="#{changePasswordController.changePassword}"
update=":changePasswordFormId :actionSuccessDialogId"
oncomplete="if(#{changePasswordController.doneChange}){actionSuccessDialogVar.show()}; if(#{changePasswordController.doneChange}){changePWDialog.hide();}">
<f:setPropertyActionListener target="#{functionSuccessBean.actionName}" value="#{msg.changePassword}"/>
<f:setPropertyActionListener target="#{functionSuccessBean.description}" value="#{msg['actionSuccess']}"/>
</p:commandButton>
the problem is: I debugged when I click on this button, before the oncomplete called the doneChange set to true. I have only one suspection: when the button is rendered, the oncomplete event is determined. Because when I open this dialog again, that doneChange is still true and works as I want. I ran out of ideas how to make it work.
How can I make it react the doneChange boolean in real time? Does it work with some binding? I tried primefaces home tutorials but with no success.
Thanks in advance

I found a solution by a help of a non-stackoverflow friend. It appears I used it wrong way, and needed to add a callbackparam.
I needed to add in the Bean:
RequestContext.getCurrentInstance().addCallbackParam(
"doneChangeParam",
doneChange
);
And oncomplete changed to:
oncomplete="if(
args && args.doneChangeParam)
{
actionSuccessDialogVar.show(); changePWDialog.hide();
}"

Related

oncomplete with commandButton isn't working

I have a nested datatable that has an Edit command button, that shows a dialog modal,
<p:commandButton value="Edit" oncomplete="PF('editStudy').show()" type="button">
<p:ajax event="click" listener="#{queryStudiesBean.setRenderDialog(true)}" update="editDialogStudy" />
<p:ajax event="click" listener="#{queryStudiesBean.setEditableStudyIndex(studyIndex)}" update="editDialogStudy: />
<p:ajax event="click" listener="#{queryStudiesBean.setEditablePatientIndex(patientIndex)}" update="editDialogStudy" />
</p:commandButton>
I was fixing the issue of keeping the rows of the child datatable expanded after updating, I was following this answer , but I faced another problem that once I load the datatable page, even before I click on the Edit button, the dialog commandButton that has the update attribute gets evaluated,
<p:commandButton process="#form" update="#form,:form2:patient-dt:#{queryStudiesBean.editablePatientIndex}:study-dt" action="#{queryStudiesBean.updateStudy()}" oncomplete="PF('editStudy').hide()" value="Save" styleClass="fixed-button-size" />
, this gives null error as patientIndex is still null, as I didn't even click on the edit button of the datatable to set the patientIndex.
So I managed to solve this by adding rendered="#{queryStudiesBean.renderDialog}" attribute to the dialog.
Now I have difficulties setting this boolean to true in the edit button action, the dialog doesn't shows right now, in the above code, I used oncomplete, and set the boolean value in <p:ajax> (as both action attribute, and <f:setPropertyActionListener> doesn't work for me, I was thinking that the boolean will be set to true before the oncomplete gets called, so the dialog shows, but this is not happend, can someone explains to me why? I saw alots of posts but no one worked for me.
full datatable code
full dialog code
I'm using:
primefaces 6.2,
java8
If your update="#form,:form2:patient-dt:#{queryStudiesBean.editablePatientIndex}:study-dt references parentIndex, it will already been called when the button is rendered.
Your update="editDialogStudy" needs to be update=":editDialogStudy" because it's
inside a row of a datatable.
You update the form, but the rendered is outside the form, so it
won't be updated. Put a <h:panelGroup... around the dialog and update
the panelGroup

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.

PrimeFaces p:ajax event=change and p:commandButton action

I am having some trouble with my application. I have a <p:inputText> with a <p:ajax> listener for the change event. I also have a <p:commandButton> on my page. Both the ajax listener and <p:commandButton> work as expected when only attempting to invoke one. The problem occurs when user edits <p:inputText> and while still focused on the field, attempts to press the <p:commandButton> which triggers the change event ajax listener (expected) but the <p:commandButton> is not invoked (not expected).
Here is my code:
<p:inputText id="code"
value="#{myBean.code}" >
<p:ajax event="change"
listener="#{myBean.method1(myBean.code)}"
update="#(form :input:not(button))" />
</p:inputText>
<p:commandButton id="searchButton"
value="Click me"
action="#{myBean.method2(myBean.code)}"
process="#this code"
update="#form"
oncomplete="PF('myDlg').show()" />
I have read this question but the answer didn't seem to solve the issue for me.
I have tried processing the button on the ajax listener and I tried putting the button in a different form and not updating that form from the ajax listener but I can't figure it out. Is what I am trying to do even possible?
Thanks in advance for any help.
If your project is running on JSF 2.2 runtime, you can utilize passthrough attributes from namespace http://xmlns.jcp.org/jsf/passthrough
I had the same issue (button doesnt work on 1st press, on next presses it works) and solved it on following way:
Add namespace to your page
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
Add oninput attribute to p:inputText (no need for p:ajax)
<p:inputText id="code" value="#{myBean.code}" pt:oninput="onTextChanged()"/>
Add p:remoteCommand bellow
<p:remoteCommand delay="300" name="onTextChanged"
actionListener="#{myBean.method1(myBean.code)}"
update="#(form :input:not(button))" />
(Delay is not necessary but it gives better performance if text is typed fast.)
oninput attribute will help your input fields to detect any kind of change event: typing, deleting, copying, pasting, cutting,etc... and via p:remoteCommand to pass them to managed bean.
And you will also solve "button" issue.
Sorry for my english.
I found another workaround for this issue.
Advantage against approved answer - no additional requests to server on user input.
I realized that the problem is that the button onclick handler is not called.
But I noticed that the onmousedown handler is called. So I added an onmousedown handler where I shedule onclick call. In the onclick handler I check if the method has already been called or not. And if it was, I cancel the event. So onclick executes only one time for one button click.
Page markup:
<p:commandButton id="searchButton"
...
onclick="return fixOnclick(event)"
onmousedown="return fixOnmousedown(event)"
</p:commandButton>
Javascript:
fixOnmousedown: function (e) {
const target = $(e.target);
target.data("eventToProcess", null);
setTimeout(function () {
target.trigger("click");
}, 10);
return true;
}
fixOnclick: function (e) {
const target = $(e.target);
if (target.data("eventToProcess") == null) {
target.data("eventToProcess", e);
}
return target.data("eventToProcess") === e;
}

have to press command button twice

I'm working on building a web page and notice now that I have to press the command button twice. Any command button has the same problem, so I figured I would add and action listener on one of them to see if I could see something.
<h:form id="formP">
<p:commandButton id="temp" value="photos" actionListener="#{viewBacking.debugBreakpoint()}" action="userPhoto" />
</h:form>
The backing bean has
public void debugBreakpoint() {
int i = 0;
i++;
}
Unfortunately, this does help. It hits my breakpoint only after the second press. I suspect that some field somewhere isn't passing validation but I would like some method of detecting what exactly is going wrong - why do I need the second push? Is there some option I can turn on in Glassfish, or something else where I can look at a dump of debug information? I can ignore the dump until everything is stable and then see what exactly is happening when I press the button for the first time.
Is there any such tool which I can use?
That can happen when a parent component of the given <h:form> has been rendered/updated by another command button/link with <f:ajax>. The given form will then lose its view state which it would only get back after submitting the form for the first time. Any subsequent submits will then work the usual way. This is caused by a bug in JSF JS API as descibred in JSF issue 790 which is fixed in the upcoming JSF 2.2.
You need to fix the another command button/link with <f:ajax> to explicitly include the client ID of the given <h:form> in the render.
<f:ajax render=":somePanel :formP" />
Another way is to replace this <f:ajax> by a PrimeFaces <p:commandLink> or <p:commandButton> so that you don't need to explicitly include the client ID of all the forms. PrimeFaces's own JS API has namely already incorporated this fix.
add event="onclick" in your p:commandbutton
I guess that will sort it out.
or you can add this ajax="false" property in your commandButton
<p:commandButton ajax="false" action="#{userController.create}" value="#{bundle.CreateUserSaveLink}"></p:commandButton>
I ran into the same issue. The solution was simple, instead of having both an actionListener and an action, just convert the actionListener method to return a string to where you want to navigate to and use it as the method for the action (and don't have an actionListener).
In simple terms: only use an action (do not use an actionListener on a commandButton that is submitting a form).
Please check your binding with bean.
bean fields should be String or non primitive.

Resources