Posted by Claudiu on 30th September 2009

Selective rendering of elements in JSF, Ajax4JSF and RichFaces

When you need conditional rendering inside an Ajax4JSF <a4j:repeat> the JSF <c:if> tag will not work. You can remedy this problem by using an alternative solution.

Problem

Inside an <a4j:repeat var="_counter" value="#{bean.list}"> the <c:if> tag will not recognize the _counter variable. You won’t even notice it doesn’t work because no errors will be logged.
As an alternative you can use the <rich:togglePanel> component.

Solution

Let’s take this example as an alternative to the JSF <c:if> tag:

<rich:togglePanel id="switch" value="#{beanEntity.selectedPanel}"
            switchType="server"
            initialState="panelOne" stateOrder="panelOne,panelTwo">
<f:facet name="panelOne">
      <rich:panel>
      <h:outputtext value="This is the first panel"/>
      <rich:toggleControl value="switch panel"
            for="switch" switchToState="panelTwo"/>
       </rich:panel>
</f:facet>

<f:facet name="panelTwo">
      <rich:panel>
            <h:outputtext value="This is the second panel"/>
            <rich:toggleControl for="switch" value="switch panel"
                  switchToState="panelOne"/>
      </rich:panel>
</f:facet>
</rich:togglePanel>

You have a few parameters which you can use:

1. switchType which can be either of

  • client renders all the panel’s faces, and switches between them on the client side
  • ajax renders only one panel at a time, and the switch is done by communicating with the server dynamically
  • server renders only one face at a time, the switch is made on page refresh

If you need something rendered only if a condition is true, server is the best option.

2. initialState controls what the first rendered panel should be. If it’s not specified the panels are rendered in the order specified by stateOrder. If that’s missing also they are rendered in the order the panels are declared.

For switching between panels you can use <rich:toggleControl>. This is similar to a link and has a value attribute (text to be shown). With the id attribute you can style content using css.

3. switchToState specifies to which state should the togglePanel control switch to. If this is not specified it will switch to the next panel in the stateOrder list. A toggleControl can be declared anywhere on the page. Not just inside a togglePanel control. It just needs the for attribute to point to the right component id.

Like in the case of the <c:if> tag, let’s say you want to render something if #{bean.booleanProperty} is false. You do the boolean check on the bean side. Then you set a bean property (eg. String panelState) to the value of panelOne if the booleanProperty is true. And subsequently to panelTwo if the booleanProperty is false. The togglePanel will have the initialState set to #{bean.panelState}.

Conclusion

The <c:if> JSF tag will just refuse  - without any error notice – to parse the counter variable coming from a wrapping <a4j:repeat> tag. It can be a little bit of a stretch but if you have problems with the <c:if> tag the above solution offers a good way to do conditional rendering.

    1 Response

  1. Endre says:

    Updated post for the case for the specific problem of the mix of <a4j:repeat> and <c:if> @Inocknoldloda