问题
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>
:
This requires minimum Mojarra 2.1.18, otherwise JSF view scoped beans will fail to restore.
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 viaExternalContext
.
See also:
- JSTL in JSF2 Facelets... makes sense?
来源:https://stackoverflow.com/questions/17946529/dynamic-uiinclude-with-uifragment-component-with-rendered-false-still-make-in