Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c:choose not working in JSF

I have three values and I want one component to be rendered in the case of first two values and another component for the third value

Below, I have my page :

page.xhtml

<ui:repeat value=#{bean.value} var="data">
<c:choose>
 <c:when  test="#{data.thirdValue == 'content'}">
   <h:outputText value="Wrong value"/>
 </c:when>
 <c:otherwise>
  Correct!
 </c:otherwise>
</c:choose>
</ui:repeat>

This is how my page is defined. I have also added the following namespace : xmlns:c="http://java.sun.com/jsp/jstl/core.

I tested whether, the value defined inside test for <c:when> returns "true" or "false" and it does.

My problem is that the <c:when> is never evaluated. The <c:otherwise> value is always rendered. Am I missing something? Is it because of the the conditional rendering being inside <ui:repeat> that the when is not evaluated?

Any help will be most appreciated. Thanks in advance

like image 363
sciFi Avatar asked May 27 '13 08:05

sciFi


2 Answers

You need to remove the c:choose, because as @Jens stated on the comments, they are processed in different phases. You can use JSTL in tandem with JSF, but have to respect the order they are resolved. read the fine answers by BalusC, he rocks.

As for your needs, you can use the rendered attribute, to conditionally output your text:

<ui:repeat value="#{bean.value}" var="data">
    <h:outputText rendered="#{data.thirdValue == 'content'}" value="Wrong value"/>
    <h:outputText rendered="#{data.thirdValue != 'content'}" value="Correct!"/>
</ui:repeat>
like image 104
Mindwin Avatar answered Oct 07 '22 12:10

Mindwin


Just to add to Mindwin's answer, you need to understand that <c:choose> is a tag handler, when <ui:repeat> is a UI component. The former is evaluated while component tree is being built, and the latter - while the view is being rendered, i.e. at a later time. In this light, depenence upon var of <ui:repeat> is what is wrong with your code, as it hasn't been evaluated when <c:choose> comes into play.

There are two things to be remembered here.

Use an iterative tag handler, <c:forEach>, with your contents:

<c:forEach items=#{bean.values} var="data">
    <c:choose>
        <c:when  test="#{data.thirdValue == 'content'}">
            <h:outputText value="Wrong value"/>
        </c:when>
        <c:otherwise>
            Correct!
        </c:otherwise>
    </c:choose>
</c:forEach>

With this approach both tags run at the same time (view is being built), so the conflicts won't occur. Just remember that in case your bean is view scoped it will be recreated upon every request.

Use UI component with rendered attribute:

<ui:repeat value=#{bean.values} var="data">
    <h:outputText rendered="#{data.thirdValue == 'content'}" value="Wrong value"/>
    <ui:fragment rendered="#{data.thirdValue != 'content'}">
        <h1>Correct</h1>
    </ui:fragment>
</ui:repeat>

In this case everything runs as well at the same time (view is being rendered). Note that you can render a whole bunch of HTML with, for example, <ui:fragment>, as well as some certain JSF tags like <h:outputText>, by using a rendered attribute.


Ultimately, go ahead with the classic post: JSTL in JSF2 Facelets… makes sense?, to get a full understanding of relationship between tag handlers and UI components.

like image 43
skuntsel Avatar answered Oct 07 '22 14:10

skuntsel