conditional display for multiple fields - JSF 2.0 / Primefaces

13,508

Solution 1

Rendered is the recommended way to display (or not) a component.

If you can group them together, then setting the rendered attribute of the container is perfectly valid. I'd do that in preference to setting the rendered attribute on each individual component.

The only minor disadvantage is if the display is dynamic (you change the backing bean value), and you need to redisplay the container, it doesn't exist. You need to wrap the container in another container which you then reRender.

Solution 2

You can use h:panelGroup as a container for this. It has a rendered property and will result in a span (by default).

Solution 3

I had to resort to using because when I wrapped my column values in another component (like ui:fragment, or h:panelGroup) to use the rendered for that component the panelGrid treated the entire ui fragment as one column which really messed up my table.

<c:if test="#{myBean.displayThese}">
   <!-- columns to display for this condition -->
</c:if>
<c:if test="#{!myBean.displayThese}">
   <!-- other stuff to display -->
</c:if>

surprisingly, <c:otherwise> didn't seem to work for me though.

Share:
13,508
Bogdan
Author by

Bogdan

Updated on June 24, 2022

Comments

  • Bogdan
    Bogdan almost 2 years

    What is the best strategy for conditionally displaying multiple elements (for example a list of fields that depends on a bean value)?

    Possible solutions I thought of:

    1. JSTL <c:if ... > clause. From what I understand using JSTL with JSF is discouraged
    2. Using the "rendered" attribute of most components. Unfortunately when I have to deal with a lot of fields it becomes clumsy to set them on each one...
    3. Putting the elements on a container and setting the rendered attribute on the container

    Option 3 seems the most sensible but I don't know what component to use to wrap those fields. It needs to be a component that doesn't affect the layout...

    I could use a span as a wrapper and set a CSS visible property, but the fields will still be rendered, just invisible.

    Any thoughts?

    Update:

    Here's some actual layout code. I've tried both <h:panelGroup> & <ui:fragment>. Using any of those tags will put all my fields in a single <td>, which I admit, it makes sense because I'm putting a single top level element in my panelGrid.

    The only thing that works the way I want is #2 from the list above.

        <h:panelGrid columns="2">
            <!-- fields if person -->
            <ui:fragment rendered="#{createEntity.entityType eq 'fizica'}">
                <h:outputLabel value="Prenume: " />
                    <h:inputText value="#{createEntity.person.firstName}" />
                <h:outputLabel value="Nume familie: " />
                    <h:inputText value="#{createEntity.person.familyName}"  />
                <h:outputLabel value="CNP: " />
                    <h:inputText value="#{createEntity.person.cnp}" />
                <h:outputLabel value="Date carte identitate: " />
                    <h:inputText value="#{createEntity.person.idCardInfo}" />
                <h:outputLabel value="Cetatenie: " />
                    <h:inputText value="#{createEntity.person.country}" />
            </ui:fragment>
    
            <!--  fields for company  -->
            <ui:fragment rendered="#{createEntity.entityType eq 'juridica'}">           
                <h:outputLabel value="Denumire firma"  />
                    <h:inputText value="#{createEntity.company.name}" />
                <h:outputLabel value="CUI"  />
                    <h:inputText value="#{createEntity.company.cui}" />
                <h:outputLabel value="Registrul Comertului"  />
                    <h:inputText value="#{createEntity.company.regCommerceNo}" />
            </ui:fragment>
        </h:panelGrid>