如何让 Richfaces 组件在按需加载的弹出窗口中工作?
Posted
技术标签:
【中文标题】如何让 Richfaces 组件在按需加载的弹出窗口中工作?【英文标题】:How to get Richfaces components to work in demand loaded popup? 【发布时间】:2013-12-28 00:25:36 【问题描述】:在使用 RF 4 的单页 JSF 2.1 应用程序中,会有很多弹出窗口用于不同的表单来编辑数据。仅当单击 GUI 中的某个按钮时才应显示表单。由于我无法在原始页面加载时创建所有弹出窗口,包括内容和支持 bean,因此我使用延迟加载创建它们,类似于此问题中提出的第二个答案:Richfaces modalPanel load with Ajax
<a4j:outputPanel id="container">
<c:if test="#popupController.isPopupVisible(popup.id)">
<f:subview id="view">
<rich:popupPanel id="popup" show="true" modal="false" autosized="true" resizeable="false" style="z-index:10000; background-color:#FFF;">
<f:facet name="header">
<h:outputText value="#popup.title" />
</f:facet>
<f:facet name="controls">
<h:form id="closeButtonform">
<a4j:commandLink id="closePopup" render="container" action="#popupController.hidePopup(popup.id)" onbeforedomupdate="#rich:component('popup').hide(); return false;">X</a4j:commandLink>
</h:form>
</f:facet>
<rich:extendedDataTable id="table" value="#itemBean.items" var="item">
...
</rich:extendedDataTable>
</rich:popupPanel>
</f:subview>
</c:if>
</a4j:outputPanel>
<h:form id="openButtonForm">
<a4j:commandLink id="openPopup" render="container" action="#popupController.showPopup(popup.id)" />
</h:form>
backing bean 不做任何魔术,只是存储数据,所以它们被忽略了。
目前的工作是打开和关闭显示/隐藏弹出窗口的弹出链接,并且仅在需要时创建包括弹出内容的支持 bean 在内的内容。我遇到的问题是弹出窗口内的组件(本示例中的 rich:extendedDataTable)已显示,但 JSF/Richfaces/Ajax 以某种方式未正确处理它们。让我进一步详细说明:当 c:if 测试在页面初始显示期间评估为 true 时,一切正常,javascript RichFaces.$('popup:view:table')
产生与表格关联的正确 RF JavaScript 对象。我可以随意关闭/打开弹出窗口,没有任何问题。但是,当页面加载时最初不存在弹出窗口然后使用按钮打开时,我收到以下 JS 错误。
Uncaught TypeError: Cannot call method 'addCSSText' of undefined popup.xhtml:1
(anonymous function) popup.xhtml:1
runScripts jsf.js.xhtml:1
doUpdate jsf.js.xhtml:1
response jsf.js.xhtml:1
richfaces.queue.response richfaces-queue.js.xhtml:413
jsf.ajax.response richfaces-queue.js.xhtml:50
onComplete jsf.js.xhtml:1
AjaxEngine.req.xmlReq.onreadystatechange jsf.js.xhtml:1
Uncaught TypeError: Cannot call method 'addLocale' of undefined popup.xhtml:1
(anonymous function) popup.xhtml:1
runScripts jsf.js.xhtml:1
doUpdate jsf.js.xhtml:1
response jsf.js.xhtml:1
richfaces.queue.response richfaces-queue.js.xhtml:413
jsf.ajax.response richfaces-queue.js.xhtml:50
onComplete jsf.js.xhtml:1
AjaxEngine.req.xmlReq.onreadystatechange jsf.js.xhtml:1
Uncaught TypeError: undefined is not a function popup.xhtml:1
(anonymous function) popup.xhtml:1
runScripts jsf.js.xhtml:1
doUpdate jsf.js.xhtml:1
response jsf.js.xhtml:1
richfaces.queue.response richfaces-queue.js.xhtml:413
jsf.ajax.response richfaces-queue.js.xhtml:50
onComplete jsf.js.xhtml:1
AjaxEngine.req.xmlReq.onreadystatechange
然后相同的 JavaScript RichFaces.$('popup:view:table')
产生 undefined
并且弹出窗口中的表格无法正确呈现。似乎所有依赖于 RF JavaScript(如列格式、滚动条等)的东西都没有初始化,在某些情况下也没有应用 CSS。在这里,我关闭/打开弹出窗口的频率也无关紧要,它总是坏掉。
有什么想法可以直接在 JSF 中或在打开按钮的 oncomplete 上的 JavaScript 中解决这个问题吗?
【问题讨论】:
虽然它可能不是问题的核心,但不要使用嵌套表单。如果您需要限制执行范围,请使用<h:form>
,然后使用<a4j:region>
之类的内容。
谢谢@Makhiel,实际上我没有嵌套表单。我从我的代码中剥离了一点点。我现在修好了,看看<a4j:region>
是否适用于这种情况。
【参考方案1】:
问题是当一个组件被动态添加到 JSF 视图树时,它并没有正确加载该组件的资源依赖关系。
例如当rich:extendedDataTable
组件出现在树中时,JSF 从ExtendedDataTableRenderer
读取它的资源依赖关系,例如其中一个依赖关系是@ResourceDependency(library="org.richfaces", name = "extendedDataTable.js")
,target
定义默认为head
,因此该资源作为子资源添加到h:head
在视图树中。
在我看来,JSF 检测此类添加并在 ajax 请求完成时加载新资源是合理的(RichFaces 3 ajax 引擎曾经这样做,但由于 JSF2/RichFaces4 JSF 承担了全部责任并实现了自己的 ajax 引擎) .但是 JSF 不会加载添加到头部的资源。
可能的解决方案/解决方法:
在初始页面加载时加载所有资源。 如果您启用资源打包,那么它将完成 - 将加载包含所有 RichFaces 资源的单个文件。对于您可能希望禁用打包(以便于调试)的开发环境,您可以在模板中添加以下技巧,以强制所有资源在初始页面加载时加载.
<c:if test="#initParam['javax.faces.PROJECT_STAGE'] eq 'Development'">
<!-- Force pre-loading all the resources (js/css/etc) of the specified components as they may appear in JSF tree dynamically. -->
<rich:extendedDataTable rendered="false"/>
<!-- Other components go here. -->
</c:if>
让 JSF 以某种方式加载更新后的h:head
的资源。这只是一个想法,但它可能会引导你去做一些事情。例如。如果你这样做render="@all"
- 它的工作速度要慢得多,但会根据需要加载所有内容,也许有一种方法可以让 JSF 渲染头部区域。
【讨论】:
非常感谢,就是这样。以上是关于如何让 Richfaces 组件在按需加载的弹出窗口中工作?的主要内容,如果未能解决你的问题,请参考以下文章
小谢第18问:如何让element-ui的弹出框每次显示的时候初始化,重新加载元素?
小谢第18问:如何让element-ui的弹出框每次显示的时候初始化,重新加载元素?