Alternative to Ui:Fragment in Jsf

Alternative to ui:fragment in JSF

Since ui:fragment doesn't support rendered most of IDE (like Netbeans mark it as error BUT it works because in JSF parameters are inherited)

This is actually a bug in JSF 2.0 Facelets tag file declaration (in Mojarra, that's the com/sun/faces/metadata/taglib/ui.taglib.xml file). The rendered attribute is overlooked and missing in the tag file declaration (and also in the JSF 2.0 <ui:fragment> tag documentation), while it is really present in the UIComponent. The IDE validation is based on the tag file declarations and hence it gives a misleading validation error. This issue is fixed in JSF 2.1, the missing attribute is added to the tag file declaration (and also in the JSF 2.1 <ui:fragment> tag documentation).

If either just ignoring the IDE warnings or upgrading to JSF 2.1 is not an option, then you can consider using the <h:panelGroup> component instead:

<h:panelGroup rendered="#{condition}">
<h:outputText value="text 1"/>
<h:outputText value="text 2"/>
<h:outputText value="text 3"/>
</h:panelGroup>

It outputs nothing anyway if you don't specify the id, style, styleClass and like attributes, else a simple <span> will be rendered.

If all what you have is plain vanilla HTML (i.e. no JSF components), then you can also consider using <f:verbatim>.

<f:verbatim rendered="#{condition}">
text 1
text 2
text 3
</f:verbatim>

However, the <f:verbatim> is deprecated in JSF 2.0 (which in turn has also a documentary bug by the way, the JSF 2.0 <f:verbatim> tag documentation does not mention deprecation, but the JSF 2.1 <f:verbatim> tag documentation does).

Should I use ui:fragment with the render attribute to conditionally render HTML tags in Facelets with JSF 2.2?

There's no limitation in that. Not even for wrapping ui:fragment.

Basically:

  • In order just to control the inner content, with no extra HTML generation use
    ui:fragment.
  • To generate an extra HTML span element, use h:panelGroup.
  • To generate an extra HTML div element, use h:panelGroup layout="block".

The HTML you have inside isn't a problem. JSF, being a server side framework, performs all the HTML building/rendering job in the server, so the JSF/facelet tags get translated to HTML before the response being sent. All the plain HTML you use inside will remain HTML.

However, beware of using tag handlers inside UI Components when migrating from 1.x. Tag handlers (ui:include, c:if, c:forEach) evaluate before the UI Components (which tipically contain rendered clauses). This has been a source of conflict in JSF 2.

Value expressions still evaluated despite ui:fragment rendered=false

<ui:fragment rendered> prevents it from rendering the HTML output, but it doesn't prevent it from ending up in JSF component tree and being eligible for state saving.

Use <c:if test> instead. It runs during view build time instead of view render time and thus the whole bunch won't end up in JSF component tree at all.

Or, if you have this all inside an <ui:repeat var="property">, and you are using Mojarra, then upgrade to at least 2.1.29 or 2.2.7 wherein this state saving bug was fixed.

See also:

  • JSTL in JSF2 Facelets... makes sense?
  • PropertyNotFoundException on conditionally rendered subclasses in ui:repeat

facelets ui:fragment ignores rendered attribute

You seem to be using <ui:fragment> inside an iterating tag/component where the #{price} is actually the currently iterated variable, such as the JSTL <c:forEach> tag, or the JSF <h:dataTable> or <ui:repeat> component while using an early version of Mojarra. In those situations, the #{price} is not available in EL scope at the point it's been evaluated.

You need the <h:panelGroup rendered> instead or to upgrade the Mojarra version to the latest.

JSF -- Alternative to rendered=?

If the getter does nothing else than just returning a (cached) boolean property, then I really don't see any pains. There's no alternative to it. Best what you could to to improve the performance is to cache it in either the model (lazy loading) or the view (c:set). The cost of getter method invocation in turn is fully negligible.

Why is ui:fragement not rendered inside ui:composition

Anything outside <ui:define> and <ui:composition> is ignored during building the view and don't end up in JSF component tree.

You need to put <ui:fragment> inside <ui:define>.

<ui:composition template="../../WEB-INF/tpl/admin/template.xhtml">
<ui:define name="sectionTitle">Admin</ui:define>

<!-- Logged as Admin -->
<ui:define name="body">
<ui:fragment rendered="#{user.admin}">
<h3>Welcome</h3>
<p>Please choose an administration task!</p>
</ui:fragment>
</ui:define>

</ui:composition>

An alternative is to use JSTL <c:if> as that runs during view build time already:

<ui:composition template="../../WEB-INF/tpl/admin/template.xhtml">
<ui:define name="sectionTitle">Admin</ui:define>

<!-- Logged as Admin -->
<c:if test="#{user.admin}">
<ui:define name="body">
<h3>Welcome</h3>
<p>Please choose an administration task!</p>
</ui:define>
</c:if>

</ui:composition>

See also:

  • How to include another XHTML in XHTML using JSF 2.0 Facelets?
  • JSTL in JSF2 Facelets... makes sense?

c:if test seems to always evaluate true in JSF2 Facelets

The XML namespace is invalid. It should be

xmlns:c="http://java.sun.com/jsp/jstl/core"

Yes, astonishingly with the /jsp part in the URI! The one without /jsp works only in Facelets 1.x for JSF 1.x. If you have checked the generated HTML output in the webbrowser, you should have noticed as well that the <c:if> is left unparsed in the HTML output.


That said, you should prefer JSF components over JSTL tags, unless technically impossible (i.e. when you actually want to control the building of the view, not rendering of the view). The h:panelGroup as you found out yourself is a good candidate, however the ui:fragment is a nicer choice since it has less overhead.

<ui:fragment rendered="#{not empty title}">
<h1>#{title}</h1>
</ui:fragment>

Note that due to a mistake of the JSF guys in the <ui:fragment> tag definition file of the initial JSF 2.0 version, Netbeans will jerk that the tag doesn't support the rendered attribute, but this is untrue. It certainly supports it. It has been fixed in JSF 2.1 tag definition.

See also:

  • JSTL in JSF2 Facelets... makes sense?
  • Alternative to ui:fragment in JSF
  • Conditional rendering of non-JSF components (plain vanilla HTML and template text)


Related Topics



Leave a reply



Submit