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, useh:panelGroup
. - To generate an extra HTML
div
element, useh: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
How to Create a New Packaging Type for Maven
Java Import VS Code Performance
Apache Commons Equals/Hashcode Builder
Should I Retrieve Database Record in Struts2 View Layer
Parsing Nested JSON Data Using Gson
How to Use Sqoop in Java Program
Merging Two JSON Documents Using Jackson
What's the Use of Session.Flush() in Hibernate
Eclipse Reading Stdin (System.In) from a File
How Java Do the String Concatenation Using "+"
How to Handle It with Scanner (Java)
Java.Lang.Noclassdeffounderror: Org.Slf4J.Loggerfactory
Calling Getters on an Object VS. Storing It as a Local Variable (Memory Footprint, Performance)
When Does the Main Thread Stop in Java