验证失败时保持 <p:dialog> 打开
Posted
技术标签:
【中文标题】验证失败时保持 <p:dialog> 打开【英文标题】:Keep <p:dialog> open when validation has failed 【发布时间】:2012-12-28 23:36:34 【问题描述】:我有一个 CRUD 页面,它在 Primefaces 数据表中显示来自查询(域对象列表)的数据。
<p:dataTable
id="negozi"
var="n"
value="#nController.theListFromQuery"
rowKey="#n.id"
selection="#nController.selected"
selectionMode="single">
<p:column headerText="Field1">
<h:outputText value="#n.f1" />
</p:column>
<p:column headerText="Field2">
<h:outputText value="#n.f2" />
</p:column>
<p:column style="width:4%">
<p:commandButton
actionListener="#nController.prepareEdit(n)"
update=":editDialogId"
oncomplete="editDialog.show()"
value="Edit" />
</p:column>
...
点击编辑按钮会显示一个对话框:
<p:dialog
header="Edit N"
widgetVar="editDialog"
id="editDialogId">
<h:form id="formDialog">
<h:panelGrid id="editDialogTable" columns="2" cellpadding="10" style="margin:0 auto;">
<p:outputLabel for="field1" value="F1:" />
<p:inputText id="field1" value="#nController.selected.f1" />
<p:outputLabel for="field2" value="F2:" />
<p:inputText id="field2" value="#nController.selected.f2" />
<p:commandButton
value="Confirm"
actionListener="#nController.doEdit"
update=":form"
oncomplete="editDialog.hide()"
rendered="#nController.selected.id!=null" />
...
它有效。现在我想将 F1 设为必填字段。
我在 inputText 字段中添加了“必需”属性,会发生什么?
当我尝试确认没有必填字段的表单时,实体没有被编辑(这是正确的)但对话框已关闭(这是不对的!)
当我重新打开对话框时,我可以在必填(和无效)字段上看到红色突出显示。
如果表单无效,我想要阻止对话框关闭。
我必须写一些 JS 还是 JSF 会帮助我?
【问题讨论】:
【参考方案1】:PrimeFaces ajax 响应将args
对象放入具有validationFailed
属性的范围内。你可以利用它。
oncomplete="if (args && !args.validationFailed) PF('editDialog').hide()"
(args
预检查是必要的,以便在请求期间抛出异常时不会导致 JS 错误)
您可以将其重构为可重用的 JS 函数,如下所示。
oncomplete="hideDialogOnSuccess(args, 'editDialog')"
function hideDialogOnSuccess(args, dialogWidgetVar)
if (args && !args.validationFailed)
PF(dialogWidgetVar).hide();
【讨论】:
【参考方案2】:这篇文章现在已经三年了,但我发现它很有帮助,所以我的发现可能对其他人有所帮助。
至少在 PF 5.x 中,BalusC 提供的解决方案似乎必须以两种方式进行修改。 (1) 将“args”参数添加到 oncomplete 事件处理程序的调用中,以及 (2) 使用 PF primefaces 原语来识别 PF 表中的小部件。这是我正在使用的代码:
oncomplete="hideDialogOnSuccess(args, PF('editDialog'))"
function hideDialogOnSuccess(args, dialogWidgetVar)
if (args && !args.validationFailed)
dialogWidgetVar.hide();
【讨论】:
您没有获得太多声誉,但您可以建议对公认的答案进行编辑。相反,您将获得“现实世界”的声誉和赞赏;-) 永远不会少……都赞成 BalusC 更新了他的答案,所以我的答案现在无关紧要了。见他。 在我在这里发表评论之前他已经这样做了(查看时间戳)对不起...感谢您的发现和分享【参考方案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)" />
【讨论】:
如何做到“最干净”?您建议使用 11 行函数而不是简单地添加现成可用的变量检查的选项? 好吧..我明白你的意思..但这里的事情是做一个“透明隐藏”;我的意思是......你总是做一个常规的 hide() 无论它是否经过验证(而不是有时测试);您要求到处隐藏,例如: oncomplete="editDialog.hide()" 并且不在乎验证是否会失败;它将在“下面”处理...【参考方案4】:要保持对话框在验证失败时打开,您只需将 commandButton 设置如下:
<p:commandButton value="save"
action="#YourBean.yourActionMethod"
oncomplete="if (!args.validationFailed) PF('yourDialogWidgetVar').hide()"/>
我将在这里留下一个完整的例子:
<h:form id="ad-form">
<p:dialog id="ad-dialog" widgetVar="adDialog" modal="true"
closeOnEscape="true" resizable="false" header="Addreass">
<p:messages id="a-msgs" closable="true" />
<h:panelGrid columns="2" id="ad-painel-dialog" >
<p:outputLabel value="Country" for="country" />
<p:inputText id="country" style="width:100%"
value="#clientSaverBean.editableAddress.country" />
<p:outputLabel value="City" for="city" />
<p:inputText id="city"
value="#clientSaverBean.editableAddress.city" />
<p:outputLabel value="Zip-Code" for="zipcode" />
<p:inputText id="zipcode"
value="#clientSaverBean.editableAddress.zipCode" />
<p:outputLabel value="Street" for="street" />
<p:inputTextarea id="street"
value="#clientSaverBean.editableAddress.street" />
<p:outputLabel value="Number" for="number" />
<p:inputText id="number"
value="#clientSaverBean.editableAddress.number" />
<h:panelGroup />
<f:facet name="footer">
<p:commandButton value="save"
action="#clientSaverBean.saveAddress"
process=":ad-form:ad-dialog"
update=":ad-form:a-msgs :ad-form:ad-painel-dialog :client-form:ad-table"
oncomplete="if (!args.validationFailed) PF('adDialog').hide()"/>
</f:facet>
</h:panelGrid>
</p:dialog>
</h:form>
【讨论】:
以上是关于验证失败时保持 <p:dialog> 打开的主要内容,如果未能解决你的问题,请参考以下文章
HTTP 状态 401 - 身份验证失败:解码传入 SAML 消息时出错