提交后发生validation错误时,请保持p:对话框打开

最小示例对话框:

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

我想要做的是有mbean.saveMethod以某种方式阻止对话框closures,如果有一些问题,只通过咆哮输出一条消息。 这是一个validation器不会帮助的情况,因为没有办法告诉someValue是否有效,直到提交到后端服务器。 目前我使用可见属性来做到这一点,并将其指向mbean中的布尔型字段。 这样的工作,但它使用户界面变慢,因为popup或closures对话框需要击中服务器。

如果ajax请求本身成功(即没有networking错误,未捕获exception等), onsuccess运行,而不是如果成功调用操作方法。

给定一个<p:dialog widgetVar="testDialog">你可以移除onsuccess并用saveMethod() PrimeFaces RequestContext#execute()replace它:

 if (success) { RequestContext.getCurrentInstance().execute("PF('testDialog').hide()"); } 

注意: PF()是在PrimeFaces 4.0中引入的。 在较老的PrimeFaces版本中,您需要使用testDialog.hide()

如果您不希望使用特定于视图的脚本oncomplete控制器,则可以使用oncomplete来提供具有boolean validationFailed属性的args对象:

 <p:commandButton ... oncomplete="if (args &amp;&amp; !args.validationFailed) PF('testDialog').hide()" /> 

if (args)检查是必要的,因为在发生ajax错误时它可能不存在,并且当您尝试从它获得validationFailed失败时导致新的JS错误; &amp; 而不是&强制性的,在这个答案中解释的原因,必要时重构JS函数,你像oncomplete="hideDialogOnSuccess(args, testDialog)"调用。


不幸的是,PrimeFaces不支持RichFaces已经支持的内容:在on*属性中on* EL进行请求时重新评估。 否则,你也可以做到这一点:

 <p:commandButton ... oncomplete="if (#{not facesContext.validationFailed}) PF('testDialog').hide()" /> 

使用你的命令button的oncomplete属性和真正简单的脚本将会帮助你很多。

你的对话框和命令button将类似于这样的:

 <p:dialog widgetVar="dialog"> <h:form id="dialogView"> <p:commandButton id="saveButton" icon="ui-icon-disk" value="#{ui['action.save']}" update=":dataList :dialogView" actionListener="#{mbean.save()}" oncomplete="handleDialogSubmit(xhr, status, args)" /> </h:form> </p:dialog> 

一个脚本会是这样的:

 <script type="text/javascript"> function handleDialogSubmit(xhr, status, args) { if (args.validationFailed) { dialog.show(); } else { dialog.hide(); } } </script> 

我刚刚search了这个解决scheme 。 基本上,这个想法是使用actionListener而不是button的动作,在支持bean中添加callback参数,然后检查button的oncomplete方法。 部分代码示例:

JSF第一:

 <p:commandButton actionListener="#{myBean.doAction}" oncomplete="if (!args.validationFailed &amp;&amp; args.saved) schedulesDialog.hide();" /> 

豆类:

 public void doAction(ActionEvent actionEvent) { // do your stuff here... if (ok) { RequestContext.getCurrentInstance().addCallbackParam("saved", true); } else { RequestContext.getCurrentInstance().addCallbackParam("saved", false); } } 

希望这可以帮助别人:)

我使用这个解决scheme:

JSF代码:

 <p:dialog ... widgetVar="dlgModify" ... > ... <p:commandButton value="Save" update="@form" actionListener="#{AdminMB.saveTable}" /> <p:commandButton value="Cancel" oncomplete="PF('dlgModify').hide();"/> 

备份bean代码:

 public void saveTable() { RequestContext rc = RequestContext.getCurrentInstance(); rc.execute("PF('dlgModify').hide()"); } 

我相信这是最干净的解决scheme。 这样做,你不需要改变你的button代码 。 该解决scheme覆盖隐藏函数原型。

 $(document).ready(function() { PrimeFaces.widget.Dialog.prototype.originalHide = PrimeFaces.widget.Dialog.prototype.hide; // keep a reference to the original hide() PrimeFaces.widget.Dialog.prototype.hide = function() { var ajaxResponseArgs = arguments.callee.caller.arguments[2]; // accesses oncomplete arguments if (ajaxResponseArgs && ajaxResponseArgs.validationFailed) { return; // on validation error, prevent closing } this.originalHide(); }; }); 

这样,你可以保持你的代码:

 <p:commandButton value="Save" oncomplete="videoDetalheDialogJS.hide();" actionListener="#{videoBean.saveVideo(video)}" /> 

最简单的解决scheme是没有任何“widget.hide”,既不在onclick,也不在oncomplete。 删除隐藏function,只是把

 visible="#{facesContext.validationFailed}" 

为对话框标记