Fire download after button click method finished - ajax

Currently I´m struggling with downloading a file after a method finishes.
<p:commandButton id="someID"
icon="ui-icon-folder-collapsed"
actionListener="#{bean.myMethod}"
ajax="true" value="test">
</p:commandButton>
myMethod does some fancy long Process stuff and takes some time. My Need is to offer a download after myMethod finshes.
My Method calls a download a method to do some. Similar to the method here download function SO
As Long as I Processing: myMethod I show a "working indicator"
<p:ajaxStatus onstart="PF('dia').show()"
oncomplete="PF('dia').hide()" />
<p:dialog widgetVar="dia" modal="true" draggable="false"
closable="false" resizable="false" showHeader="false">
<h:outputText value="sometext" />
<p:graphicImage value="./img/ajax-loader.gif"></p:graphicImage></p:dialog>
I learned that I can't start a download from Ajax call (which the command Button from Primefaces starts per default). When changing the attribute ajax to false, myMehtod processes and show the download dialog after. Problem is during this I have no "working indicator" shown.
Primeface has this solution: primeface download
Now my Question is it possible to start a method from the Button (and show the "working indicator") and when the method finishes still show the download dialog via fileDownload ?

Related

Trigger command button action immediately after input text's blur listener

I have a PF's input text with ajax blur event and a command button that executes some action. If I enter some text in inputText and click on a commandButton, an ajax blur listener is executed, not a commandButton action, which is pretty much expected.
Example code:
<p:inputText id="inTest" value="#{bean.input}" >
<p:ajax event="blur" listener="#{bean.doOnBlur}" />
</p:inputText>
<p:commandButton id="btnTest" action="#{bean.doBtnClick}" />
Is there any way to execute both methods sequentially (first doOnBlur and then doBtnClick) and how do I achieve that?
Using PF 5.3 (also tried with 6.0), MyFaces 2.0.17, runnino on WebSphere Portal 7 (it's a portlet).

Closing dialog doesnt work

I'm using primefaces 5.0 and I have this situation:
<composite:implementation>
<p:dialog id="confirmDialog#{cc.attrs.someParam}"
rendered="#{cc.attrs.nextState.warnRequired}" severity="alert" resizable="false" modal="#{cc.attrs.modal}"
widgetVar="confirmation#{cc.attrs.someParam}">
<p:commandButton value="#{msg[cc.attrs.nextState.buttonKey]}" icon="#{nextStatus.icon}"
action="#{someActionCalled}"
update="#{cc.attrs.update}" process="#{cc.attrs.process}"
oncomplete="if (!args.validationFailed) { PF('confirmation#{cc.attrs.someParam}').hide(); }">
</p:commandButton>
<p:commandButton id="decline" value="#{msg['action.cancel']}" icon="ui-icon ui-icon-cancel"
onclick="PF('confirmation#{cc.attrs.someParam}').hide()" />
</p:dialog>
</composite:implementation>
When i click "decline" / cancel button, confirmDialog is closed / hides. Thats ok.
Obviusly confirmation#{cc.attrs.someParam} can find widgetVar and closes this dialog.
But when i click first button to confirm and take some action in back bean i get :
Widget for var 'confirmationSomeParam' not available!
primef...mefaces (line 1)
detailed error: TypeError: PF(...) is null
{cc.attrs.someParam}
is passed into component. Its evaluated clean and values are there ( obviusly because second button can close dialog.
So its very strange that first button cant find this dialog widgetVar and second one can ?
So i had time again to check this critical part of my application and im posting here so someone in future maybe will find this usefull :)
I have added p:remoteCommand under both buttons in code:
<p:remoteCommand name="somethingToDo" update="#{cc.attrs.update}" />
and in first button i have removed update param.
Why ? Because as error says, it could not find some dialogId ( in this example 'confirmation332m' ) and because of that update param, which was updating whole form, dialog was removed / updated.
So i moved update param from button to remote command and in
onComplete i just call somethingToDo(); after all validation is checked.
Maybe its not best solution but for now it works ;)
PF forum link ( for future problems ): http://forum.primefaces.org/viewtopic.php?f=3&t=37851

The Rich:commandLink and rich:commandButton on a dynamically rendered popup panel do not work in IE 8

I have created a JSF application using Myfaces 2.1.12 and Richfaces 4.3.3. On normal browsers the application works fine, but the client insists that he also needs to use a "browser" - IE8, version 8.0.7601. I am having a bunch of problems.
I have a rich:extendedDataTable on the main form. Clicking a row is to open a popup with the details (that is rendered and filled with the data from the selected row). The popup can also be called from a toolbar, this way it displays the details of the row that was selected when the page was first loaded.
The table is defined as follows (column definition removed for clarity)
<h:form>
<rich:extendedDataTable id="table" rowClass="row" rows="15"
value="#{scheduleController.allSchedules}" var="schedule" selectionMode="single"
selection="#{scheduleListBean.selectedSchedule.selection}" clientRows="15">
<a4j:ajax render="scheduleDetails, toolbar, transferListPopup" event="selectionchange"
listener="#{scheduleController.scheduleSelectionChanged}"
oncomplete="#{rich:component('scheduleDetailsPopup')}.show()"/>
...
</rich:extendedDataTable>
</h:form>
The popup contains a couple of panel grids, one of wich contains some buttons.
<h:panelGrid columns="2" styleClass="alignTop" id="scheduleDetails">
...
<rich:panel header="#{generalProperties.controls}">
<h:panelGrid columns="4">
<a4j:commandLink styleClass="btn" type="button"
render="table#body, transferDetailsPanel, destinationPanel, datesPanel"
oncomplete="if (#{facesContext.maximumSeverity == null}) #{rich:component('scheduleDetailsPopup')}.hide()"
status="pleaseWait" action="#{scheduleController.saveSchedule}"
value="#{generalProperties.save}" />
<h:commandButton class="btn" action="#{scheduleController.changeScheduleStatus}"
value="#{applicationProperties.changeStatus}" status="pleaseWait" type="button"
disabled="#{scheduleController.currentSchedule.id == null}">
<rich:componentControl target="changeScheduleStatusPopup" operation="show" />
</h:commandButton>
<h:commandButton class="btn" value="#{generalProperties.delete}" status="pleaseWait" type="button"
disabled="#{scheduleController.currentSchedule.id == null}">
<rich:componentControl target="removeSchedulePopup" operation="show" />
</h:commandButton>
<a4j:commandButton styleClass="btn" type="button"
render="fileTable, transferDetailsPanel, destinationPanel, datesPanel"
disabled="#{scheduleController.currentSchedule.id == null}"
oncomplete="if (#{facesContext.maximumSeverity == null}) #{rich:component('transferListPopup')}.show()"
status="pleaseWait" value="#{applicationProperties.transferHistory}" />
</h:panelGrid>
</rich:panel>
</h:panelGrid>
The disabled="#{scheduleController.currentSchedule.id == null}" part checks the bean if anything is selected as the popup is also used to add new rows.
Everything works fine on firefox. On IE8:
clicking the commandLink does not work(nothing happens, besides a "#"
that is appended to the url in the browser) when the popup is called from the
extended data table (rendered), but works when it is called from the
toolbar.
clicking the commandButton does not work(page is reloaded instead of an ajax request beeing executed) when the popup is called from the extended data table (rendered), but works when it is called from the
toolbar.
if I remove the type="button" from command buttons, then clicking them causes the entire page to be reloaded
What am I missing?
The answer was in the question itself. I rebuilt the UI so that no buttons are rendered in ajax requests. This way it works both on IE 8 and IE 9.
Ie.: Instead of setting the disabled attribute based on a bean and rendering the buttons I had to use two instances of each of those buttons. I did that by extracting a form into a composite component using composite:insertChildren just to inject buttons in the proper state and having two instances of the form on the page, showing the right one when the user clicked new schedule / edit schedule.
The drawback of this method is that I had to set the render attribute of the components that show the popup to something different then forms (in this case - panels), which would be an issue if I used Mojarra (see this question: javax.faces.ViewState is missing after ajax render)

Primefaces how to erase validation fails in dialog when reopen the dialog

I have a required input field in a p:dialog. If firstly I submit nothing for the field, a validation error happens on that field. Then I close the dialog and reopen it, the validation error still exists. What can I do to eliminate the validation error when close the dialog?
You should use the p:resetInput on the element that you have to open the dialog.
For example if you use a p:commandButton
<p:commandButton value="Open dialog" update=":dialogId" oncomplete="PF('dialogWidget').show()" >
<p:resetInput target=":dialogId" />
</p:commandButton>
This will reset the cached values (including the validation messages) upon opening the dialog.
I was able to reproduce your case and you could do the following:
Make your dialog closable="false".
Add a Cancel button that will hide the dialog.
Add a resetInput component from Primefaces Extensions inside your Cancel button. This will clear the form validations and values.
Here is an example that assumes your dialog as a widgetVar named wvDialog.
<p:commandButton value="Cancel" immediate="true" onclick="wvDialog.hide()">
<pe:resetInput for="myDialogFormId />
</p:commandButton>
You could even call a bean method in the button actionListener if you need.
I hope it helps.
Update the p:dialog or p:message every time you submit the Form.
You can do that by using update attribute of p:commandButton.
<p:commandButton update="ID_OF_DIALOG" />

How to show ajaxstatus for dynamic Primefaces components

I have noticed that pretty much all PF components that have 'dynamic' attribute set to 'true' will only show up after a short delay (which is understandable), and also will not trigger ajax start/stop event.
This is my (perfectly working) Ajax status component, actual dialog contents omitted for brevity:
<p:ajaxStatus onstart="statusDialog.show();" onsuccess="statusDialog.hide();" onerror="errorDialog.show();"/>
This is a dynamically loaded dialog. It needs to get data from backing beans:
<p:dialog modal="true" widgetVar="confDialog" position="center" id="confD" dynamic="true">
<p:panelGrid>
<p:row>
<p:column>
<h:outputText value="Date"></h:outputText>
</p:column>
<p:column>
<h:outputText value="#{myBean.currentDate}">
<f:convertDateTime locale="#{myBean.currentLanguage}" type="both" dateStyle="full" timeStyle="full" timeZone="#{myBean.currentTimeZone}"></f:convertDateTime>
</h:outputText>
</p:column>
</p:row>
</p:panelGrid>
<p:commandButton value="Close" type="button" onclick="confDialog.hide();">
</p:commandButton>
</p:dialog>
A commandbutton that does something and displays dynamically loaded confirmation dialog:
<p:commandButton value="Do it" type="submit" ajax="true" process="#form"
action="#{bean.processForm}"
oncomplete="if(!args.validationFailed){confDialog.show();}"
update="confD #form"/>
Ajax status dialog is displayed while the commandbutton submits the data to backing bean and gets data back. Then ajax status dialog disappears, there is a delay of 1-2 seconds, and confirmation dialog is shown.
The same happens with dynamically loaded tabs (in PF tabView component).
Why isn't my ajax status dialog displayed during dynamic component load? How can I show it?
EDIT:
thanks to #partlov I figured out a solution without overriding PF function, by adding JQ ajax start/stop handler to the dynamically loaded dialog:
jQuery(document).ready(function() {
confDialog.getJQ().ajaxStart(function(){statusDialog.show()});
confDialog.getJQ().ajaxStop(function(){statusDialog.hide()});
});
As written in Primefaces documentation <p:ajaxStatus> just intercepts global AJAX requests, and this request is not global. There is no easy way to do this what you want. As time of loading of dialog is short I really don't see point for this. Only solution, as I think, is to overload Primefaces dialog JavaScript methods.
Primefaces calls loadContents() method when dialog content is loaded so you can override this method for this. I don't advice you to do that, because this is undocumented and can be changed in future versions of Primefaces:
jQuery(document).ready(function() {
var oldLoadContents = PrimeFaces.widget.Dialog.loadContents;
PrimeFaces.widget.Dialog.loadContents = function() {
statusDialog.show();
oldLoadContents();
}
});
This should show your dialog on dynamic loading. You can use onShow attribute of p:dialog to close your dialog:
onShow="statusDialog.hide()"

Resources