当提交后发生验证错误时,保持 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 以某种方式阻止对话框在出现问题时关闭,并且只通过咆哮输出消息。在这种情况下,验证器没有帮助,因为在将保存提交到后端服务器之前,没有办法判断 some Value 是否有效。目前,我使用可见属性执行此操作,并将其指向 mbean 中的一个布尔字段。这样做是可行的,但是它会降低用户界面的速度,因为弹出或弹出对话框需要击中服务器。

79291 次浏览

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

给定一个 <p:dialog widgetVar="yourWidgetVarName">,你可以移除 onsuccess并在 saveMethod()中用 PrimeFaces RequestContext#execute()代替它:

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

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

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

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

if (args)检查是必要的,因为当 Ajax 错误发生时它可能不存在,因此当您试图从中获取 validationFailed时会导致一个新的 JS 错误; 由于 这个答案中解释的原因,&amp;而不是 &是必需的,如果需要,重构到您调用的 JS 函数,如 当验证失败时,保持 < p: Dialogue > 打开所示。

然而,如果没有验证错误,操作方法被成功触发,并且由于例如服务方法调用中的异常,您仍然希望保持对话框打开,那么您可以通过显式调用 FacesContext#validationFailed(),从内部支持 bean 操作方法手动触发 validationFailedtrue。例如。

FacesContext.getCurrentInstance().validationFailed();

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

我相信这是最干净的解决方案。 这样做,你 不需要改变你的按钮代码。 此解决方案重写了 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 代替按钮的操作,并且在后台 bean 中添加回调参数,然后检入按钮的 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);
}
}

希望这对某些人有所帮助:)

我使用这种方法:

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

最简单的解决方案是不使用任何“ widget.hide”,不使用 onclick,也不使用 oncomplete。删除隐藏函数,然后把

visible="#{facesContext.validationFailed}"

用于对话框标记