我有一个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成为必填字段。
我添加"required"属性到inputText字段,发生了什么?
当我试图确认没有所需字段的表单时,实体未被编辑(这是正确的),但对话框已关闭(这是不对的!)
当我重新打开对话框时,我可以看到必需的(无效的)字段上的红色高亮。
我想要的是防止对话框关闭,如果表单是无效的
我必须写一些JS还是JSF会帮助我?
PrimeFaces ajax响应将一个具有validationFailed
属性的args
对象放在作用域中。你可以好好利用它。
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();
}
}
这篇文章已经发表三年了,但我发现它很有帮助,所以我的发现可能会对其他人有所帮助。
在PF 5。至少,BalusC提供的解决方案似乎必须在两个方面进行修改。(1)将"args"参数添加到oncomplete事件处理程序的调用中,(2)使用PF primefaces原语来识别PF表中的小部件。下面是我使用的代码:
oncomplete="hideDialogOnSuccess(args, PF('editDialog'))"
function hideDialogOnSuccess(args, dialogWidgetVar) {
if (args && !args.validationFailed) {
dialogWidgetVar.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)}" />
要在验证失败时保持对话框打开,您只需要按如下方式设置命令按钮:
<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" width="400"
closeOnEscape="true" resizable="false" header="Addreass">
<p:messages id="a-msgs" closable="true" />
<h:panelGrid columns="2" id="ad-painel-dialog" width="100%">
<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>