Is there any generally acceptable way of solving issues like this one?
You basically want to fire an ajax request first and in its oncomplete check if it’s successful, and then trigger a synchronous request to download the file (note that you can’t download files with ajax). You could make use of FacesContext#validationFailed()
(or OmniFaces Faces.validationFailed()
) to mark the validation fail state which is available via args
object which PrimeFaces injects in the oncomplete
function context (note that ajax related attributes such as oncomplete
don’t work when ajax is disabled).
Something like this:
<p:commandButton
value="Export"
action="#{bean.export}"
oncomplete="if (args && !args.validationFailed) PF('download').jq.click()" />
<p:commandButton
widgetVar="download"
styleClass="ui-helper-hidden"
action="#{bean.download}" ajax="false" />
public void export() {
// Prepare file locally.
if (fail) {
// Show message your way and then set validation failed as below.
Faces.validationFailed();
}
}
public void download() throws IOException {
Faces.sendFile(file, true);
// Delete local file afterwards?
}
Note that a hidden <p:commandButton>
is being used instead of <p:remoteCommand>
as the latter doesn’t support ajax="false"
.