PrimeFaces fileUpload触发异表单必填校验如何解决
PrimeFaces 10 跨表单触发校验问题修复
问题场景
使用PrimeFaces 10版本时,页面包含两个独立表单:
- 表单1:嵌套在模态对话框组件内,包含必填输入框控件,代码如下:
<p:dialog widgetVar="myDlg" id="myDlg" modal="true" width="600"> <h:form enctype="multipart/form-data" id="myDlgForm"> <p:inputText id="myInput" value="#{myInput}" required="true"/> </h:form> </p:dialog>
- 表单2:页面主区域的文件上传表单,承载p:fileUpload高级上传组件,代码如下:
<h:form id="fileUploadForm" enctype="multipart/form-data"> <p:messages id="messages" showDetail="false" closable="true"> <p:autoUpdate/> </p:messages> <p:fileUpload listener="#{myFileUPloadView.handleFileUpload}" process="@this" mode="advanced" multiple="true" sizeLimit="1000000" fileLimit="6" widgetVar="fileUpload"/> </h:form>
异常表现
在主表单执行文件上传操作时,本应独立的对话框表单内的必填输入框会触发校验提示,阻断上传流程。
根因说明
该问题核心诱因是DOM结构出现非法表单嵌套:HTML规范不支持form标签嵌套,如果将<p:dialog>标签写在主上传表单fileUploadForm的标签内部,PrimeFaces渲染对话框时默认会把控件移动到DOM树其他位置,最终形成外层上传表单包裹内层对话框表单的结构。此时提交外层表单会自动采集内层表单的所有输入控件、触发校验规则,哪怕给fileUpload设置了process="@this"也无法绕过。
修复方案
按优先级依次操作即可解决:
- 调整对话框标签位置:把
<p:dialog>组件移到所有<h:form>标签外层,作为页面body的直接子节点放置,从源码层面避免表单嵌套写法。 - 给对话框添加appendTo配置:在
<p:dialog>标签上增加属性appendTo="@(body)",强制PrimeFaces把对话框渲染到body节点最末尾,彻底和主表单的DOM层级隔离。修改后的对话框标签示例:<p:dialog widgetVar="myDlg" id="myDlg" modal="true" width="600" appendTo="@(body)"> - 可选加固配置:如果对话框默认是关闭状态,可以给对话框追加
dynamic="true"属性,配置后对话框关闭状态下不会把内部表单控件渲染到DOM树中,从根源上杜绝控件被其他表单提交采集的可能;同时可以给p:fileUpload组件追加partialSubmit="true"属性,强化局部提交的范围限制,只采集process属性指定的控件数据。
注意:不要通过取消对话框内输入框的required规则绕过问题,这种方式会破坏对话框本身的表单校验逻辑,属于治标不治本的方案。
内容的提问来源于stack exchange,提问作者Sam Donato
相关产品推荐
相关产品推荐

