Minimal example dialog:
<p:dialog header="Test Dialog"
widgetVar="testDialog">
<h:form>
<p:inputText value="#{mbean.someValue}"/>
<p:commandButton value="Save"
onsuccess="testDialog.hide()"
actionListener="#{mbean.saveMethod}"/>
</h:form>
</p:dialog>
What I want to be able to do is have the mbean.saveMethod somehow prevent the dialog from closing if there was some problem and only output a message through growl. This is a case where a validator won't help because there's no way to tell if someValue is valid until a save is submitted to a back end server. Currently I do this using the visible attribute and point it to a boolean field in mbean. That works but it makes the user interface slower because popping up or down the dialog requires hitting the server.
The
onsuccess
runs if ajax request itself was successful (i.e. there's no network error, uncaught exception, etc), not if action method was successfully invoked.Given a
<p:dialog widgetVar="testDialog">
You could remove theonsuccess
and replace it by PrimeFacesRequestContext#execute()
insidesaveMethod()
:Note:
PF()
was introduced in PrimeFaces 4.0. In older PrimeFaces versions, you needtestDialog.hide()
instead.If you prefer to not clutter the controller with view-specific scripts, you could use
oncomplete
instead which offers anargs
object which has a booleanvalidationFailed
property:The
if (args)
check is necessary because it may be absent when an ajax error has occurred and thus cause a new JS error when you try to getvalidationFailed
from it; the&
instead of&
is mandatory for the reason explained in this answer, refactor if necessary to a JS function which you invoke likeoncomplete="hideDialogOnSuccess(args, testDialog)"
as shown in Keep <p:dialog> open when validation has failed.This latter solution (with a little rewrite) should work for plain jsf
h:commandButton
in combination with anf:ajax
It's unfortunate that PrimeFaces does not support what RichFaces already supports: request-time re-evaluation of EL in
on*
attributes. You would otherwise also be able to do just this:I've just googled up this solution. Basically the idea is to use actionListener instead of button's action, and in backing bean you add callback parameter which will be then check in button's oncomplete method. Sample partial code:
JSF first:
Backing bean:
Hope this helps someone :)
I believe this is the cleanest solution. Doing this you don't need to change your buttons code. This solution overrides the hide function prototype.
This way, you can keep your code like:
The easiest solution is to not have any "widget.hide", neither in onclick, neither in oncomplete. Remove the hide functions and just put
for the dialog tag
Using the
oncomplete
attribute from your command button and really simple script will help you a lot.Your dialog and command button would be something similar to this:
An the script would be something like this:
I use this solution:
JSF code:
Backing bean code: