I am trying to conditionally build a custom list using <ui:repeat>
. On every occurrence of -1 as item-value in list, I need to add a line break.
I tried to use <c:if>
inside <ui:repeat>
for that, but it does not seem to work. It always evaluates false
.
<ul>
<ui:repeat value="#{topics.list}" var="topicId" >
<li>#{topicId}</li>
<c:if test="#{topicId eq -1}"> <br/> </c:if>
</ui:repeat>
</ul>
Is this possible?
Not with JSTL tags, no. They run during view build time, not during view render time. You can visualize it as follows: when JSF builds the view, JSTL tags run from top to bottom first and the result is a pure JSF component tree. Then when JSF renders the view, JSF components run from top to bottom and the result is a bunch of HTML. So, JSTL and JSF don't run in sync as you'd expect from the coding. At the moment your <c:if>
JSTL tag tag runs, the #{topicId}
variable which is set by <ui:repeat>
JSF component isn't available in the scope.
Instead of using <c:if>
, you need to specify the condition in the rendered
attribute of the JSF component of interest. As you've actually none, you could wrap it in a <ui:fragment>
.
<ul>
<ui:repeat value="#{topics.list}" var="topicId" >
<li>#{topicId}</li>
<ui:fragment rendered="#{topicId eq -1}"><br/></ui:fragment>
</ui:repeat>
</ul>
Alternatives are <h:panelGroup>
<h:panelGroup rendered="#{topicId eq -1}"><br/></h:panelGroup>
or in your specific case <h:outputText escape="false">
<h:outputText value="<br/>" escape="false" rendered="#{topicId eq -1}" />
as both also emits nothing else to the HTML output when no client side attributes are specified.
Unrelated to the concrete problem, that's the wrong place for a <br/>
. It would be ignored by any webbrowser respecting the HTML specification. Don't you mean it to be inside the <li>
? Or better, give it a class
and let CSS give it a margin-bottom
.