复合组件 (composite component) 以下简称cc。
在 JSR-314 的邮件列表中有个讨论,http://lists.jboss.org/pipermail/jsr-314-open-mirror/2009-September/001526.html
问题的焦点是,cc 被设计为一个黑盒结构,组件如果内部含有 naming container,那么它 *应该* 不要在页面的组件实例中插入”奇怪“的 client id。
比如说,child.xhtml:
<cc:implementation>
<h:form id="xyz">
<cc:renderFacet ..>
以及
<my:child id="aaa">
<f:facet>
<commandButton id="c">
那么,commandButton 的 clientId 应该是 aaa:c,而不是 aaa:xyz:c。
但是,问题并不仅仅在于 client id。如果是 client id 变得更加简短,那么页面作者倒是更省心了。
原因就在于,client id 是反应 component tree 的,也就是说,commandButton 在 renderFacet 的机制下,并不是挂接到 form 下面,而是挂在了 my:child 的下面。也就是说 renderFacet 将 f:facet 重新定向到 cc 上了。
那么能不能不要重新定向呢?
简单的说,不可以。但是,有几个特殊情况:
1. 如果 cc 里面要用到 f:facet,而页面上传递 f:facet 给 cc 里面的同名 f:facet,那么你可以用 cc:insertFacet。
2. 用 cc:insertChildren.
这里, cc:insertFacet 和 cc:insertChildren 不会重定向。但是, cc:insertFacet 只能用来传递 f:facet,而 cc:insertChildren 只有一个锚点。
那么能不能用 insertChildren 的方式插入一个 facet 呢?
事实证明是可以的,经过摸索通过自定制一个 tag handler,来模拟 insertFacet 的行为,但绕过外层的 f:facet 即可。
源代码请参考我在 SO 上的回复:http://stackoverflow.com/questions/7891650/using-compositeinsertfacet-renderfacet-does-not-work-inside-tdatatable/9091313#9091313