dynamic ui:include with ui:fragment: component with rendered false still make inside component tree

与世无争的帅哥 提交于 2020-01-01 07:20:24

问题


I am force to use a very old version of MyFaces 2.0.5 I think, and dynamic include with EL cause so much problem, so I switch to static include with ui:fragment

<ui:fragment rendered="#{filtersPopup.filterFileName == 'checkBoxFilters'}">
    checkBoxFilters
    <ui:include src="/analytics/checkBoxFilters.xhtml" rendered="#{filtersPopup.filter != null}"/>
</ui:fragment>
<ui:fragment rendered="#{filtersPopup.filterFileName == 'DateRelativeFilter'}">
    DateRelativeFilter
    <ui:include src="/analytics/DateRelativeFilter.xhtml" rendered="#{filtersPopup.filter != null}"/>
</ui:fragment>
<ui:fragment rendered="#{filtersPopup.filterFileName == 'listboxFilter'}">
    listboxFilter
    <ui:include src="/analytics/listboxFilter.xhtml" rendered="#{filtersPopup.filter != null}"/>
</ui:fragment>

With this, it still complain about duplicate id because I use same id on couples of these source file. So it seems that even rendered should be false, it still make it to the component tree. However duplicate id is fine. I can fix that easy, so now when I submit form, I got this exception

 /analytics/checkBoxFilters.xhtml at line 24 and column 118 value="#{filtersPopup.filter.groups}": Property 'groups' not found on type ListBoxFilter

so as you can see from the exception, it ListBoxFilter is the object I want, so only include ListBoxFilter.xhtml, but is being accessed checkBoxFilters.xhtml hence the error. Any idea how to fix this issue please?


回答1:


The <ui:include> doesn't extend from UIComponent. It's a tag handler. It does thus not support the rendered attribute at all. It's also nowhere listed in the tag documentation.

<ui:fragment> is indeed an UIComponent. So basically you end up with all those 3 include files being included during view build time and thus all 3 physically end up in JSF component tree. It's only the HTML output which is conditionally rendered via <ui:fragment rendered>. You still end up with duplicate component IDs from those includes because they all end up in JSF component tree.

You should be using a taghandler like <c:if> instead of <ui:fragment> to conditionally build the JSF component tree.

So, theoretically, this should do for each of them:

<c:if test="#{filtersPopup.filterFileName == 'checkBoxFilters'}">
    checkBoxFilters
    <c:if test="#{filtersPopup.filter != null}">
        <ui:include src="/analytics/checkBoxFilters.xhtml" />
    </c:if>
</c:if>

... etc

This has however some caveats when #{filtersPopup} is a view scoped bean and/or when you're using <f:viewParam>:

  1. This requires minimum Mojarra 2.1.18, otherwise JSF view scoped beans will fail to restore.

  2. Taghandlers run during view build time. So things which runs thereafter like <f:viewParam> won't work at all. You'd need to fall back to manually grabbing HTTP request parameters via ExternalContext.

See also:

  • JSTL in JSF2 Facelets... makes sense?


来源:https://stackoverflow.com/questions/17946529/dynamic-uiinclude-with-uifragment-component-with-rendered-false-still-make-in

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