conditional display for multiple fields - JSF 2.0 / Primefaces
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:
- JSTL
<c:if ... >
clause. From what I understand using JSTL with JSF is discouraged - 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...
- 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 p开发者_Go百科ut 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>
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.
You can use h:panelGroup
as a container for this. It has a rendered property and will result in a span (by default).
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.
ugly, but maybe working for you, via conditional style:
<h:component value="foo" style="#{!myBean.displayFoo ? 'display: none;' : ''}" />
if you request is a conditional with the value of your variable of your database:
<c:if test="#{myObject.mycolumnTableDB==value1}">
<!-- columns to display for this condition -->
</c:if>
<c:if test="#{myObject.mycolumnTableDB==value2}">
<!-- other stuff to display -->
</c:if>
精彩评论