Strategy for p:fileDownload with dialog with loading
I am trying to make a loading bar after starting the download of a file. My download button is like this:
<p:commandButton id="btnFirstType"
styleClass="bt_princ"
value="Download File"
onclick="loading.show()"
ajax="false">
<p:fileDownload value="#{mbean.myFile}"/>
</p:commandButton>
<p:dialog modal="true"
widgetVar="loading"
header="Status"
draggable="false"
closable="false">
<p:graphicImage value="/loading.gif" />
</p:dialog>
And my MBean is like this:
public StreamedContent getMyFile(){
return this.getReport(Type.CSV); //I assure this works, debugged...
}
The problem is, after clicking the download button, if I start the loading dialog, the download doesn't occurr.
I thought about using p:poll to check a boolean variable so I know when the file has been generated, so I could show the dialog after clicking the button (like setting setTimeout with JavaScript), but this is maybe my mistake about how the whole thing happens. Any other suggestion?
PS1: Polling stops working after the file is downloaded, so I won't know when to close the dialod
PS2: I am using Primefaces 2.2 and can't update.
PS3: Found this workaround but 'it will' be on version 3, so I can't use it.
I did the same as suggested in the workaround posted on my question.
I downloaded the primefaces sources from my version, changed the FileDownloadActionListener class, added cookies in the response object and in my page I just started a process with setTimeout that would check cookies every 100 miliseconds, and when find it, delete it.
Related
Basically I am trying to get 2 Responses from the server while sending only 1 Request. I have a table in Primefaces, where 1 column contains a p:commandLink, by pressing this link, the page is newly loaded, data updated and a download is started in a new Tab. (in FF life is great, it works without problem, but under Chrome the new Tab is stopped from being opened and I see one the requests being canceled).
The column with the problem contains the following:
<p:commandLink id="updateData"
action="#bean.reloadPage()}"
onsuccess="document.getElementById("startDownload").onclick()">
<f:param name="id" value="#{row.id}" />
</p:commandLink>
<p:commandLink id="startDownload"
ajax="false"
style="display: none"
action="#{bean.download()}"
target="_new" />
"Funny" is that under IE and FF is working..
Apparently it had to do something with Chrome life cycle, while waiting for the "onsuccess" the original page that shot the request is already gone.. changing "onsuccess" to "onstart" had worked for me.
I am using Primefaces 4.0, JSF 2.1.11
I have a page with a button that calls a prime-faces dialog.show() and a dialog appears after filling it out click done and it refreshes the page with the new item added into a prime-faces dataTable. Everytime I click the button to open the dialog and fill it out then hit done my browser memory goes up. In automation testing once the dialog has been opened 125 times (our users could do this up to 800 times in a row) the browser runs out of memory. In IE8 at 125 items the memory usage was at 880 MB.
So my question is how do I prevent this?
more Info: Beans are viewscoped, using Glassfish 3, this issue happens in all browsers but worse in older browsers.
Steps I have taken:
1. I am doing a .show() .hide() each time on the dialog.
2. I have tried to call javascript to empty out the divs in the DOM without any success.
I have looked on primefaces issues and I dont see any memory leak reports, also if I let the page sit open the memory doesn't go up, its only when I am using the page and opening and closing the dialog.
UPDATE:
Here is some code
this form is outside the other form
<h:form id="lineItemForm">
<p:dialog id="addLineItemDialogId" widgetVar="lineItemDialog" header="Line item" width="900" resizable="false"
modal="true" showEffect="fade">
...
...
<p:commandLink value="Done"
onclick="actionStarted($(this))"
action="#{lineItemView.save}"
update=":wizardForm:lineItemWizardPanel"
oncomplete="actionComplete(); saveLineItem(args);"/>
</h:form>
The saveLineItem(args) is a javascript method that calls .hide() after validation check
Here is the call to .show() it is in the form wizardForm.
<h:form id="wizardForm"/>
...
...
<p:commandLink value="Add Item"
action="#{lineItemView.loadLineItemFromRequest(requisitionView.request)}"
process="#this"
update=":lineItemForm"
oncomplete="lineItemDialog.show()"/>
UPDATE So It ended up being a red hering. I removed the backend method call and the memory leak went away. It looks likes its the dataTable causeing the issue, with ajax. Looked it up and it is fixed in Primefaces 5
http://www.beyondjava.net/blog/primefaces-5/
I'll take a guess although I am not sure. Try structuring the code like this:
<h:body>
<h:form id="mainForm">
...
...
...
...
</h:form>
<p:dialog>
<h:form id="dialogForm">
...
</h:form>
</p:dialog>
</h:body>
And on the button you use to show the dialog use update="dialogForm".
I believe that if you update the dialog itself or one of its parents, it can result in several dialogs hiding each other. That might explain the memory usage. Besides it is best practise to have the dialogs in the end outside of the main form.
My application is managing software, and for user convenience, I want to allow them to open multiple tabs for changing parameters of more than one record at a time. But after finishing whatever they doing, the tabs stays open, and I got some complains about that. So basically my question is:
If there's any way to close browser tab that sends a request to method in my backing bean? for example:
JSF page:
<h:commandButton value="Public score"
action="#{assignmentBean.publicSelected()}">
</h:commandButton>
Bean method:
public void publicSelected() {
application.setAssignmentStatus(done);
dataAccess.mergeEntity(application);
}
is there any way to add something after merging command and close browser tab that activated method? Thanks for help
FULL CODE FOR SOLUTION I'm bad with mixing JS and JSF, so for any of you that are also bad at this I post full code solution using Tiago Vieira Dos Santos hint.
Now my button code looks like:
<h:commandButton value="Public score"
action="#{myBean.doThings}">
<f:ajax execute="#this" onevent="pop"/>
</h:commandButton>
plus on bottom of page I added code as follows:
<script type="text/javascript">
function pop(data){
if(data.status == "success"){
window.close();
}
}
</script>
now after method does what has to be done the window closes.
I think you can be use the javascript command Window.close() then you can put it on oncomplete tag or call in you managed bean using the FacesContext.
See more in this How to close current tab in a browser window?
Using an OutputLink and Javascript
<h:outputLink onclick="window.open('popup.faces', 'popupWindowName', 'dependent=yes, menubar=no, toolbar=no'); return false;" value="#">
<h:outputText value="open popup" />
</h:outputLink>
With this solution we got control over the appearance of the new browser window. And since there is no postback, there is no validation at all. This is the easiest way to open a new browser window when no model update is needed and no action has to be executed.
In order to implement a proper action handling we need to move the decision whether to open a new window to the action listener.
<h:commandLink actionListener="#{bean.openPopupClicked}" value="open popup" />
public void openPopupClicked(ActionEvent event) {
// code to open a new browser window goes here
}
I want to render using Richfaces a context menu on left click on a link-appearing text (blue text, and underline and cursor onmouseover). So, imagine a link which when clicked shows a context menu. Note that I don't care if the text is indeed a link, I just want it to appear as a link. So, even normal text would be fine, I would make it appear as a link using CSS.
I have the following conditions:
The context menu must appear on client side, without making a request.
The context menu must appear using a rich:componentControl (these "links") are inside a datatable, so the same rich:contextMenu must be re-used.
I still have not found a satisfactory solution, as each approach I have tried has caused a problem for me:
If I use h:outputText (that would be ideal), I cannot attach on it a rich:componentControl (I guess because it cannot fire an onclick event).
If I use a4j:commandLink, although I can attach a rich:componentControl, it makes a server request. I tried to add onclick="return false;" to prevent the request, but Richfaces adds the JS generated by the rich:componentControl after whatever is inside the onclick, which causes this code not to be reached at all, and of course the context menu not to appear at all.
Is there any way to do this? Please remember, no request!
You may try
<rich:componentControl disableDefault="true" ...>
According to documentation with this param componentControl should add return false; itself.
But be aware of corresponding bug: RF-5607
In case documentation lies you may use html anchors. This answer shows how to create a link with componentControl and without page refresh:
<h:outputLink value="#" id="link" onclick="return false;">
<h:outputText value="Link text"/>
<rich:componentControl attachTo="link" for="panel" operation="show" event="onclick"/>
</h:outputLink>
The onclick="return false;" prevents the anchor from scrolling the page to the clicked link.
I am writing an app using JSF 2.0.
For one of the page, there is a section of the page that takes a long time to display.
To improve the user experience, I am thinking to load the page first and then automatically do an Ajax call back to the JSF manage bean object once the page is loaded successfully after 1st load.
I am thinking to use f:event with type postAddView.
<h:outputText id="dummyId">
<f:event type="postAddToView" listener="#{mngBean.doSomething}" />
</h:outputText>
However it seems like f:event postAddToView is still being processed before the page is displayed for the first time.
The other options that I have explore is to create a hidden button and get javascript to trigger it. It works however I am just wondering if there is a nice JSF component/event that can do this instead of using java script.
Thanks for your help.
<h:commandButton id="dmyButton"
value="#{mngBean.getSomething}"
actionListener="#{mngBean.doSomething}"
style="display: none"
type="submit">
Java Script
<script language="JavaScript">
$(document).ready(function() {
if (document.getElementById('form:dmyButton').value == 'true') {
document.getElementById('form:dmyButton').click();
}
});
</script>
Thanks for all your help in advance
I think the PreRenderViewEvent is what you want.
http://javaserverfaces.java.net/nonav/docs/2.0/javadocs/javax/faces/event/PreRenderViewEvent.html
Though the docs don't show it, the preRenderViewEvent does work with f:event. I'll fix the docs presently.
PostAddToViewEvent is processed "During Restore View Phase, after a
component has been added to a view." (according to Java Server Faces 2.0 - The Complete Reference) which means it is really early in the lifecycle (Restore View is the first lifecycle phase).
I don't think that any PhaseListener will help you in this case, since they all run on the server side, not on the client side.
However, <f:ajax> can be applied to <h:body>, with event="load". I tried it, but it didn't really work, <f:ajax> wrapping <h:body> nothing happened, the other way around I got Unable to attach <f:ajax> to non-ClientBehaviorHolder parent error.