Edge中RichFaces 3.3.3的rich:modalPanel点击h:commandButton后无法再显示
嘿,我碰到过类似的老版本RichFaces在Edge下的兼容性坑,结合你的代码和描述,给你拆解下问题和解决办法:
为啥只有Edge会出这问题?
你的导出按钮用的是h:commandButton,这是同步表单提交,点击后会触发完整的页面导航(就是控制台里的HTML1300: Navigation occured.)。Chrome和Firefox在这种导航后,还能保留JSF视图的客户端状态,但Edge会把页面的DOM和JS状态重置得更彻底。
加上RichFaces 3.3.3本身是针对老IE设计的,哪怕打了IE9补丁,对Edge的支持也很有限。当你导出PDF后,虽然rich:componentControl隐藏了模态面板,但同步提交已经把服务器端printBean.showModalPanel的状态和客户端的DOM关联给冲断了——后续再点打开按钮,后台把showModalPanel设为true,但客户端的模态面板区域已经因为导航丢失了正确的渲染状态,自然弹不出来。
可行的解决方案
方案1:把导出改成AJAX提交(最推荐)
把h:commandButton换成a4j:commandButton,用异步提交代替同步导航,这样页面状态不会被重置:
<a4j:commandButton id="confirmButton" value="#{ msgs['printButton']}" actionListener="#{ printBean.onExportButton}" ajaxSingle="true"> <f:attribute name="format" value="PDF"/> <!-- 保留你原来的其他属性 --> <rich:componentControl attachTo="confirmButton" for="printConfirmationMP" operation="hide" event="onclick" /> </a4j:commandButton>
注意:如果你的PDF导出是通过ExternalContext直接写响应流,AJAX环境下可能需要调整成用a4j:mediaOutput来处理文件下载,这是RichFaces里专门用来在AJAX场景下输出文件的组件,能避免导航问题。
方案2:用JS控制模态面板显示,摆脱rendered属性依赖
RichFaces的showWhenRendered+rendered组合在Edge导航后容易失效,换成纯JS控制显示/隐藏更可靠:
- 修改打开按钮,用
oncomplete触发JS显示模态面板:
<a4j:commandButton image="/img/print.gif" styleClass="clsCursorPointer" action="#{ printBean.onExportReport}" ajaxSingle="true" oncomplete="Richfaces.showModalPanel('printConfirmationMP');" />
- 调整模态面板,去掉
rendered和showWhenRendered,默认渲染但隐藏:
<rich:modalPanel id="printConfirmationMP" autosized="true" visible="false"> <!-- 内部的form和按钮保留不变 --> </rich:modalPanel>
这样不管页面有没有导航,只要JS调用showModalPanel就能弹出面板,完全避开服务器端渲染状态的问题。
方案3:同步提交后强制刷新面板状态(应急hack)
如果实在不能改AJAX,可以在导出后强制重新渲染模态面板区域:
- 在
printBean里加个标记属性exportCompleted,导出完成后设为true - 页面底部加个短轮询的AJAX组件,检测到导出完成就刷新面板:
<a4j:poll id="exportRefreshPoll" interval="1" enabled="#{printBean.exportCompleted}" reRender="printConfirmationPanel" oncomplete="#{printBean.exportCompleted = false}" />
这个方案有点凑活,但能应急解决问题。
最后提个醒
RichFaces 3.3.3真的太老了,对现代浏览器的兼容性问题只会越来越多。如果项目有预算,尽量升级到RichFaces 4.x或者迁移到更现代的JSF框架,从根源上解决这类兼容性麻烦。
内容的提问来源于stack exchange,提问作者Egan Wolf

