Search code examples
jsfconditional-statementsajax4jsfcommandlink

Problems with conditionals in JSF


I have the code bellow:

<c:set var="show" value="#{cartBean.itemsAdded}" />

<c:if test="${show}">
    <h:form id="test1">
        <h:commandLink action="#{cartBean.foo}">this doesn't work</h:commandLink>           
    </h:form>
</c:if>

<h:form id="test2">
    <h:commandLink action="#{cartBean.foo}">this works!</h:commandLink>         
</h:form>

When show=false, show only the second link. And it works. I can reach server (I'm using debug to see this).

When show=true, both links appears. But ONLY second link works. The link inside conditional doesn't trigger the action in server.

Someone, can, please, help me?

Note: the same thing happens when I use a4j:outputPanel rendered="#{show}"


Solution

  • During processing of the form submit, JSF will re-evaluate whether the command button/link is been rendered. If it is not rendered, then it will simply skip the action.

    You need to ensure that the expression #{cartBean.itemsAdded} returns true as well when the form submit is been processed by JSF. An easy test is to put the bean in the session scope (and I assume that the isItemsAdded() is a pure getter, i.e. it contains only return itemsAdded;).

    If that did fix the problem and you'd like to keep the bean in the request scope, then add a <a4j:keepAlive> to retain the bean properties in the subsequent request.

    <a4j:keepAlive beanName="#{cartBean}" />
    

    See also:


    Unrelated to the concrete problem, you should prefer JSF tags/attributes over JSTL ones as much as possible. In this particular case, you should get rid of both JSTL <c:> tags and use the JSF-provided rendered attribute instead:

    <h:form id="test1" rendered="#{cartBean.itemsAdded}">
        <h:commandLink action="#{cartBean.foo}">this doesn't work</h:commandLink>           
    </h:form>