Ajax 提交后出现验证错误时,保持p:对话框打开

Ajax 提交后出现验证错误时,保持p:对话框打开,ajax,validation,jsf,primefaces,dialog,Ajax,Validation,Jsf,Primefaces,Dialog,最小示例对话框: 我希望能够做到的是,让mbean.saveMethod在出现问题时以某种方式阻止对话框关闭,并且只通过咆哮输出消息。在这种情况下,验证器没有帮助,因为在将保存提交到后端服务器之前,无法判断someValue是否有效。目前,我使用visible属性来实现这一点,并将其指向mbean中的一个布尔字段。这是可行的,但会使用户界面变慢,因为弹出或关闭对话框需要点击服务器。如果ajax请求本身成功(即没有网络错误、未捕获异常等),而不是成功调用操作方法,onsuccess将运行 给定

最小示例对话框:



我希望能够做到的是,让mbean.saveMethod在出现问题时以某种方式阻止对话框关闭,并且只通过咆哮输出消息。在这种情况下,验证器没有帮助,因为在将保存提交到后端服务器之前,无法判断someValue是否有效。目前,我使用visible属性来实现这一点,并将其指向mbean中的一个布尔字段。这是可行的,但会使用户界面变慢,因为弹出或关闭对话框需要点击服务器。

如果ajax请求本身成功(即没有网络错误、未捕获异常等),而不是成功调用操作方法,
onsuccess
将运行

给定一个
,您可以在
saveMethod()中删除
onsuccess
并用PrimeFaces
RequestContext\execute()
替换它:

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

如果您不想用视图特定脚本扰乱控制器,可以使用
oncomplete
,它提供了一个
args
对象,该对象具有布尔
validationFailed
属性:


if(args)
检查是必要的,因为当发生ajax错误时,它可能不存在,因此当您试图从中获取
验证失败时,它会导致新的JS错误;
&而不是
&
是必需的,原因如中所述,如有必要,重构为您调用的JS函数,如
oncomplete=“hideDialogOnSuccess(args,testDialog)”
,如中所示

但是,如果没有验证错误,并且操作方法已成功触发,并且由于服务方法调用中的异常等原因,您仍然希望保持对话框打开,那么您可以通过显式调用从backingbean操作方法内部手动触发
validationFailed
true
。例如


使用命令按钮中的
oncomplete
属性和非常简单的脚本将对您有很大帮助

您的对话框和命令按钮与此类似:

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

函数handleDialogSubmit(xhr、状态、参数){
if(args.validationFailed){
dialog.show();
}否则{
dialog.hide();
}
}

我相信这是最干净的解决方案。 执行此操作时,无需更改按钮代码。 此解决方案覆盖隐藏函数原型

$(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)}" />

我刚在谷歌上搜索过。基本上,这个想法是使用actionListener而不是button的操作,并且在backingbean中添加回调参数,该参数随后将签入button的oncomplete方法。部分代码示例:

JSF优先:

<p:commandButton actionListener="#{myBean.doAction}"
   oncomplete="if (!args.validationFailed &amp;&amp; args.saved) schedulesDialog.hide();" />
希望这对某人有所帮助:)

我使用此解决方案:

JSF代码:

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

最简单的解决方案是不在onclick和oncomplete中使用任何“widget.hide”。删除隐藏函数,只需将

visible="#{facesContext.validationFailed}" 

对于对话框标记

,使用RequestContext非常有趣。我不知道你能这么做。oncomplete中的表达式需要被否定。oncomplete=“if(args.validationFailed)…”@BalusC
oncomplete=“if(args&;!args.validationFailed)
这是我的做法。
null
检查我的代码是否不必要?@BalusC,为什么在这种情况下使用actionlistener而不是action?@Mah:我只是接管了OP的原始代码。问题不是actionlistener和action,所以我保留了OP的原始代码。但我同意,对于c来说,这不是推荐的方法如果你想知道的话。链接改为。你让我在三点后过了一天。谢谢你!
public void doAction(ActionEvent actionEvent) {
    // do your stuff here...
    if (ok) {
        RequestContext.getCurrentInstance().addCallbackParam("saved", true);
    } else {
        RequestContext.getCurrentInstance().addCallbackParam("saved", false);
    }
}
<p:dialog ... widgetVar="dlgModify" ... >
...
<p:commandButton value="Save" update="@form" actionListener="#{AdminMB.saveTable}" />
<p:commandButton value="Cancel" oncomplete="PF('dlgModify').hide();"/>
public void saveTable() {
    RequestContext rc = RequestContext.getCurrentInstance();
    rc.execute("PF('dlgModify').hide()");
}
visible="#{facesContext.validationFailed}"