1

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?

Thang Pham
  • 38,125
  • 75
  • 201
  • 285

1 Answers1

10

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:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • `filtersPopup` is a SessionScoped, is that good enough, BalusC? – Thang Pham Jul 30 '13 at 12:16
  • 1
    As to Mojarra version, yes. Only the `` problem persists. If `filterFileName` or `filter` (in)directly depend on ``, then it will fail. – BalusC Jul 30 '13 at 12:17
  • Thanks. I think that it works I dont see that issue anymore, but I ran into another one. if I have multiple `c:if` like u have above, when I form submit I ran into this exception `java.lang.IllegalStateException: Error restoring component: j_id52 at org.apache.myfaces.view.facelets.DefaultFaceletsStateManagementStrategy.restoreStateFromMap(DefaultFaceletsStateManagementStrategy.java:51 .. Caused by: java.lang.ClassCastException: [Ljava.lang.Object; incompatible with javax.faces.component._DeltaList`. If I just have 1 `ui:include` then everything work correct. Any idea, BalusC. Thank you – Thang Pham Jul 30 '13 at 12:34
  • I'm afraid that you've to upgrade MyFaces to latest. – BalusC Jul 30 '13 at 12:39
  • There is no reason why don't upgrade MyFaces to the latest (the latest artifacts are the best ones so far, with lots of improvements and bug fixes). – lu4242 Aug 05 '13 at 19:34
  • @lu4242: as far as I know, OP is using Websphere. The manual upgrade procedure is quite opaque. – BalusC Aug 05 '13 at 19:36
  • I see. In theory it should be easy to do it, because the integration points has not changed in a long time. Personally I strongly suggest upgrade, because the problem of how to deal with dynamic sections (c:if, ui:include src="#{...}" ...) was solved long time ago and requires changes some code inside jsf, in a way that can't really be avoided. – lu4242 Aug 05 '13 at 19:51