我有以下结构(内容和属性忽略):
<ui:repeat id="outerlist">
<my:compositeComponent id="myCC">
<h:panelgroup id="container">
Some content here (outputText, etc.)
<ui:repeat id="innerlist">
<h:commandButton>
<f:ajax render=":#{cc.clientId}:container" />
<!-- all closing tags accordingly -->
由于容器内的含量取决于innerlist的按钮的操作,我需要更新它。 如上图所示的作品,在没有外部的做法ui:repeat
。 但是,它未能与component not found
的错误时,有一个。
这似乎是由于该事实cc.clientId
然后本身含有外的行索引ui:repeat
,如outerlist:0:myCC:container
。 至于这个答案评论指出,这个索引ID是不是在视图树的服务器端表示可用。 相反,“行索引只存在于客户端”。 我必须承认,我不太了解这个索引是如何做的,什么是可以在服务器端。
所以我的问题是:如何JSF做索引,它是如何(在服务器上)独立的不同的“实例”一内部ui:repeat
,是有什么我试图实现与上面的代码的解决方案?
如在指定的客户机ID <f:ajax>
必须在两个由JSF的服务器侧可用
facesContext.getViewRoot().findComponent(clientId);
(以便它能以呈现其新的HTML表示对Ajax响应中找到)
并通过JavaScript的客户端
document.getElementById(clientId);
(因此,它可以被更新/被JS更换一次新的HTML内容的Ajax响应已到达)
正如<ui:repeat>
(来自“无法找到组件...”的错误观点在运行的渲染时间而已,与该行的索引客户端ID并不代表在服务器端有效成分findComponent()
但它确实代表在客户端有效的HTML元素。 基本上,你需要在客户端ID而不行索引的服务器端和一个与客户端的行索引。 但是,就不会为工作<ui:repeat>
,因为它是(不幸)无法选择单独由特定的迭代循环的组件树状态findComponent()
应该使用JSTL当正常工作<c:forEach>
并且当它在视图构建时运行,并且也实际上是在视图树,而不是仅一个被重复使用多次时呈现生成多个fullworthy JSF组件动态分配组件ID。
<c:forEach varStatus="loop">
<my:compositeComponent id="myCC">
<h:panelGroup id="container_#{loop.index}">
Some content here (outputText, etc.)
<ui:repeat id="innerlist_#{loop.index}">
<h:commandButton>
<f:ajax render=":#{cc.clientId}:container_#{loop.index}" />
然而,这有它自己的意义,在嵌套循环使用时,用复合材料部件使用,也肯定时。 您的代码是不完整的,足以给有关的见解和建议。 这将例如打破时这段代码被放置在复合部件是通过本身在渲染时间回路还重复使用多次。
也可以看看:
- JSTL在JSF2的Facelets ...有道理?
- 如何找出AJAX更新组件的客户端ID /渲染? 找不到与“酒吧”中所引用的表达“foo”的分量
作为更新:在这种特殊情况下,使用c:foreach
是不是一种选择,因为这两个名单必须是动态的(虽然这条路救了我在其他一些情况下很麻烦),相反,我添加的属性到复合组件通过一个可选的“更新范围”,像这样:
<cc:attribute name="updateScope" required="false" type="java.lang.String"
default=":#{cc.clientId}:container" />
通过设置默认情况下,我并不需要改变组件的任何用途的非循环环境。 但是,如果我想使用它里面ui:repeat
我可以通过一个ID是足够宽,以封闭外部循环的属性。 通常情况下,这将是一个h:panelGroup id="wrapper"
就在ui:repeat
。
显然,这有相当一些缺点:它的最新动态,这有可能导致很多不必要的内容被重新呈现的所有儿童。 这方面的一个讨厌的副作用是这些兄弟姐妹的错误消息和本地值复位。 在我们的网页之一,它还会导致将所有扩展面板被重置为关闭状态。
但是,如果这些问题并不重要(例如:我原来的例子提到了有没有输入字段或面板,但只有反馈的文字和动作的部件),附加属性可以是一个简单的方法来解决所描述的问题。
我只是解决了这个我自己就像这样:
update=":#{cc.clientId.replaceAll(':[0-9]+:', ':')}"