JSF Conditional includes, cause Component ID has already been found in the view

别说谁变了你拦得住时间么 提交于 2019-11-28 09:41:27
BalusC

The duplicate component ID error occurs because the both includes physically end up in the JSF component tree. The <h:panelGroup rendered="false"> doesn't prevent them from ending up in JSF component tree, instead it prevents them from generating their HTML output.

Instead of conditionally rendering their HTML output, you need to conditionally build them in the JSF component tree. JSTL is very helpful in this as it runs during view build time:

<c:if test="#{bean.insertMode eq 'SINGLE'}">
    <ui:include src="_single.xhtml" />
</c:if> 
<c:if test="#{bean.insertMode eq 'DOUBLE'}">
    <ui:include src="_double.xhtml" />
</c:if>

In case you're using Mojarra, you only need to make sure you use at least version 2.1.18 or newer, otherwise view scoped beans will behave like request scoped beans.

An alternative is to make use of EL conditional operator in src attribute (the <ui:include> itself runs as being a taghandler also during view build time):

<ui:include src="_#{bean.insertMode eq 'SINGLE' ? 'single' : 'double'}.xhtml" />

Or even use the insertMode directly as filename:

<ui:include src="_#{fn:toLowerCase(bean.insertMode)}.xhtml" />

Either way, you need to make absolutely sure that the #{bean.insertMode} is available during view build time, and also that exactly the same value is available during the restore view phase of postbacks as it was during initial render, otherwise the view would possibly be restored with the wrong include and JSF can't decode the right inputs and command anymore. Also, when you want to change the include during postback, you really need to rebuild the view (return non-null/void), or to send a redirect.

See also:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!