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

时间:2012-02-08 14:57:52

标签: ajax validation jsf primefaces 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> 

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

6 个答案:

答案 0 :(得分:146)

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

给定<p:dialog widgetVar="testDialog">您可以移除onsuccess并将其替换为RequestContext#execute()内的PrimeFaces saveMethod()

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

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

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

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

if (args)检查是必要的,因为当发生ajax错误时它可能不存在,因此当你试图从中获取validationFailed时会导致新的JS错误;由于this answer中解释的原因,&amp;而不是&是强制性的,如果需要,可以像Keep <p:dialog> open when validation has failed中所示调用oncomplete="hideDialogOnSuccess(args, testDialog)"调用的JS函数重构

后一种解决方案(稍加重写)应该适用于普通jsf h:commandButtonf:ajax


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

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

答案 1 :(得分:16)

我刚刚用Google搜索this solution。基本上我的想法是使用actionListener而不是按钮的动作,并在支持bean中添加回调参数,然后检查按钮的oncomplete方法。示例部分代码:

首先是JSF:

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

支持bean:

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

希望这有助于某人:)

答案 2 :(得分:15)

使用命令按钮中的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>

答案 3 :(得分:7)

我使用这个解决方案:

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

答案 4 :(得分:3)

我相信这是最干净的解决方案。 这样做不需要更改按钮代码。 该解决方案覆盖了隐藏功能原型。

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

答案 5 :(得分:1)

最简单的解决方案是没有任何&#34; widget.hide&#34;,既没有onclick,也没有oncomplete。删除隐藏功能,然后放入

visible="#{facesContext.validationFailed}" 

用于对话框标记