提交后发生验证错误时,请保持p:dialog打开


70

最小示例对话框:

<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以某种方式阻止对话框在出现问题时关闭,并且仅通过咆哮声输出消息。在这种情况下,验证程序将无济于事,因为在将保存提交到后端服务器之前,无法确定someValue是否有效。目前,我使用visible属性进行此操作,并将其指向mbean中的布尔值字段。那行得通,但是它使用户界面变慢,因为弹出或弹出对话框需要点击服务器。

Answers:


158

onsuccess运行,如果AJAX请求本身是成功的(即有没有网络故障,未捕获的异常等),如果不采取行动方法成功地调用。

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

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

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

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

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

if (args)检查是必要的,因为发生ajax错误时可能不存在该检查,因此在尝试获取validationFailed该错误时会导致新的JS错误。出于此答案中说明的原因,&amp;而不是&强制性的,如果有必要,请重构为调用的JS函数,如验证失败时保持<p:dialog>打开中所示。oncomplete="hideDialogOnSuccess(args, testDialog)"

但是,如果没有验证错误,并且成功触发了操作方法,并且由于服务方法调用中的异常等原因,您仍希望保持对话框打开,则可以validationFailed通过true从内部支持bean操作方法内部手动触发调用FacesContext#validationFailed()。例如

FacesContext.getCurrentInstance().validationFailed();

2
使用RequestContext非常有趣。我不知道你能做到
JOTN '02年

1
oncomplete中的表达式需要否定。oncomplete =“ if(args.validationFailed)...”
Steven Shaw

1
@BalusConcomplete="if(args &amp;&amp; !args.validationFailed)这是我的方法。是null检查在我的代码不必要的?
KeremBaydoğan2013年

1
@BalusC,为什么在这种情况下使用actionlistener而不是action?
Mahmoud Saleh 2013年

2
@Mah:我只是接管OP的原始代码。问题不是关于actionListener与action,因此我保留了OP的原始代码。但是我同意,对于您想知道的情况,这不是推荐的方法。
BalusC

16

我刚刚用谷歌搜索了这个解决方案。基本上,这个想法是使用actionListener而不是button的动作,并且在backing bean中添加回调参数,然后将其检入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);
    }
}

希望这可以帮助某人:)


链接更改为此处
vhunsicker

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>

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

3

我相信这是最干净的解决方案。这样做,您无需更改按钮代码。此解决方案覆盖了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)}" />

2

最简单的解决方案是在onclick或oncomplete中都没有任何“ widget.hide”。删除隐藏功能,然后放

visible="#{facesContext.validationFailed}" 

用于对话框标签


你让我过了三天。感谢那!
CleitonCardoso
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.