最小示例对话框:
<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中的布尔字段。这有效,但它会使用户界面变慢,因为弹出或关闭对话框需要点击服务器。
答案 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 && !args.validationFailed) PF('testDialog').hide()" />
if (args)
检查是必要的,因为当发生ajax错误时它可能不存在,因此当你试图从中获取validationFailed
时会导致新的JS错误;由于this answer中解释的原因,&
而不是&
是强制性的,如果需要,可以像Keep <p:dialog> open when validation has failed中所示调用oncomplete="hideDialogOnSuccess(args, testDialog)"
调用的JS函数重构
后一种解决方案(稍加重写)应该适用于普通jsf h:commandButton
和f: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 && 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}"
用于对话框标记