Is there a bean event for cancel button in PrimeFaces upload component? - jsf

We are using the primefaces for file upload handling in our web application. The upload component becomes visible, upon some event on the page (button pressed). We would like to be able to catch the event when CANCEL button is pressed, in order to use it to hide the upload component back. Any advise? Javascript or CSS would not do the work, as we also need to do some server logic for this.
Code:
<h:form id="uploadFileForm" enctype="multipart/form-data" rendered="#{filesMenu.enableFileUpload}">
<p:fileUpload style="font-size:12px;"
fileUploadListener="#{filesMenu.handleFileUpload}"
mode="advanced" dragDropSupport="false"
update="msgUpload , :formFilesListId , :formFilesListId:dataTableSimpleFilesId, :createNewFileFromSelectionForm"
sizeLimit="100000" fileLimit="1" allowTypes="/(\.|\/)(cfg)$/" />
<p:growl id="msgUpload" showDetail="true" />
</h:form>

Catch the cancel-button click with Javascript/JQuery. On the one hand you can invoke an hidden button on your jsf page which triggers the server logic. On the other hand you can trigger the following component from Javascript :
<p:remoteCommand name="functionName" action="#{yourBean.yourMethod}">
Catch the cancel button :
$(document).ready(function() {
$(".ui-fileUpload").on("click",".cancel",function() {
//Approach remoteCommand
functionName();
//Approach hidden button
$(".jQueryTohiddenButtonClass").click();
}
Probably you have to customize the jQuery path, so they fit to your demands.

Another option is to hide the cancel-button completely with
.ui-fileupload-cancel {
display: none;
}
and create your own button instead which calls an action/actionListener and hides the dialog.
I went even further and hid all 3 buttons and created my own save button too, which called PF('fileupload_widgetvar').upload(); in oncomplete. Then you'd need to have some javascript to make the page wait until the upload is finished, as the ajax is asynchonous so you can't redirect/hide the dialog right away. Let me know if you want that code.

Related

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.

JSF 1.2 to open external link in new tab. without distrubing current flow [duplicate]

I need to open a JSF page in a new window by POST on click of a <h:commandButton>. I know I can acheive this using the JavaScript. But I would like to achive this using JSF and not JavaScript.
How can I achieve this? I'm using JSF 2.0.
The only non-JS way is to set target="_blank" in the parent <h:form>.
<h:form target="_blank">
...
<h:commandButton value="Open in new Window" />
</h:form>
This however affects all non-ajax(!) actions which are performed in the very same form. So if you're smart, make the action which shouldn't open in a new window an ajax action. However, ajax is also JavaScript and you mentioned that you don't want to use JS (I hope you don't get shocked once you discover that PrimeFaces is actually full of JavaScript).
If you absolutely need to restrict it to a single action, then you really can't go around asking little help to JavaScript.
<h:form>
...
<h:commandButton value="Open in new Window" onclick="this.form.target='_blank'" />
</h:form>
When you restrict the target only to a single action, maybe you want to get the form in its initial state.
With the oncklick action you set the target of the form to a _blan page.
After the click, the page is opened in a new tab/page (triggers the action event).
At last, the onblur action is triggered and set the form again to its initial state (the rest of the buttons will open in the _self page)
With this code, you can restrict to only a h:commandbutton to open in a new page.
The rest of the buttons will be opened in the self page:
<h:commandButton
onclick="this.form.target='_blank'"
onblur="this.form.target='_self'"
id="listadoRebuts"
action="#{giaquaBusquedaCorte.abrirListadoRebuts}"
value="#{msg.seqVisorbtnRecibos}">
</h:commandButton>

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;
}

Primefaces commandButton download complete hide dialog

In PrimeFaces 5.1 p:commandButton press to call download action. In action to get data from DB and create pdf. When its complete to download the pdf. My problem huge data create to taken a time that time I want to show dialog box, because user that time no for further action to done. CommandButton press I show dialog but can't know how to close dialog box.If any other way to complete action to close dialog.
stud.xhtml
<p:commandButton value="download" action="#{stud.downloadAction}" onclick="PF('progressWaitDialog').show()" ajax="false" onComplete="PF('progressWaitDialog').hide();"/>
<p:dialog id="progressWaitDialog" widgetVar="progressWaitDialog" modal="true">
<h:graphicImage value="#{stud.progressWaitBar}"/>
</p:dialog>
stud.java
public string downloadAction()
{
createPdf(studenToList);
return null;
}
My doubt commanButton click open dialog but download action complete how to hide dialog?
If you are using PrimeFaces, you can take advantage of PrimeFaces.monitorDownload and <p:fileDownload>. It is documented here.
Basically, you have to change your commandButton to use an actionListener instead an action. This actionListenerprepares an org.primefaces.model.StreamedContent to stream the file you want to download. This stream has to be wired with value attribute of <p:fileDownload>.
To prepare that StreamedContent, if your createPdf(studenToList) method returns a file, it would be as easy as following:
String mime = "application/pdf";
String name = "your-file-name.pdf";
File file = createPdf(studenToList);
StreamedContent stream = new DefaultStreamedContent(file, mime, name);
The onclick event of your commandButton will call the monitorDownload javascript of PrimeFaces onclick="PrimeFaces.monitorDownload(startFaDwn, stopFaDwn);".
Finally, you have to provide your own implementation of startFaDown and stopFaDown. This is mine:
<script type="text/javascript">
function startFaDwn() {
PF('FADownloadDlg').show();
}
function stopFaDwn() {
PF('FADownloadDlg').hide();
}
</script>
As you can see, both functions open and hide a dialog as you want. You can name these functions as you want, and obviously it can do what you want, not only open/close dialog.
You won't need onComplete event, neither ajax="false" attribute.
Hope it helps!

Open new window by POST using h:commandButton

I need to open a JSF page in a new window by POST on click of a <h:commandButton>. I know I can acheive this using the JavaScript. But I would like to achive this using JSF and not JavaScript.
How can I achieve this? I'm using JSF 2.0.
The only non-JS way is to set target="_blank" in the parent <h:form>.
<h:form target="_blank">
...
<h:commandButton value="Open in new Window" />
</h:form>
This however affects all non-ajax(!) actions which are performed in the very same form. So if you're smart, make the action which shouldn't open in a new window an ajax action. However, ajax is also JavaScript and you mentioned that you don't want to use JS (I hope you don't get shocked once you discover that PrimeFaces is actually full of JavaScript).
If you absolutely need to restrict it to a single action, then you really can't go around asking little help to JavaScript.
<h:form>
...
<h:commandButton value="Open in new Window" onclick="this.form.target='_blank'" />
</h:form>
When you restrict the target only to a single action, maybe you want to get the form in its initial state.
With the oncklick action you set the target of the form to a _blan page.
After the click, the page is opened in a new tab/page (triggers the action event).
At last, the onblur action is triggered and set the form again to its initial state (the rest of the buttons will open in the _self page)
With this code, you can restrict to only a h:commandbutton to open in a new page.
The rest of the buttons will be opened in the self page:
<h:commandButton
onclick="this.form.target='_blank'"
onblur="this.form.target='_self'"
id="listadoRebuts"
action="#{giaquaBusquedaCorte.abrirListadoRebuts}"
value="#{msg.seqVisorbtnRecibos}">
</h:commandButton>

Resources