1

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}"

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Topera
  • 12,223
  • 15
  • 67
  • 104

3 Answers3

2

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>
Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Balus! Thanks a lot! I changed the scope of cartBean from request to session and now it works! Thanks again! – Topera Mar 17 '11 at 18:55
  • You're welcome. Note that putting bean in session scope has caveats. When the user opens the same page in multiple tabs/windows, the same bean would be shared which may lead to undesireable behaviour when the user executed actions from multiple tabs simultaneously. As mentioned in the answer, it was just intented as a quick test. If it worked, you'd like to keep it in request scope and use `a4j:keepAlive` to retain bean in next request from the same browser tab/window. – BalusC Mar 17 '11 at 18:57
1

WORKARROUND:

I don't want to use sessionScope, because of the danger of use this in a huge system (my case). I don't like to use keepAlive neighter, because I'm in a clutered server and many attributes are not serializable.

Anyway, I've found this workarround:

  1. Send a parameter in request (like show=true)
  2. Change the check method, adding a OR in return to see this new parameter.

MANAGED BEAN:

Before:

public boolean itemsAdded() {
    return foo; // my initial check
}

After:

public HttpServletRequest getRequest() {
        return (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
}

public boolean itemsAdded() {
    return foo || getRequest().getParameter("show") != null;
}

XHTML:

Before:

<c:set var="show" value="#{cartBean.itemsAdded}" />
<c:if test="${show}">
    <h:form id="test1">
        <h:commandLink action="#{cartBean.foo}">link</h:commandLink>           
    </h:form>
</c:if>

After:

<c:set var="show" value="#{cartBean.itemsAdded}" />
<c:if test="${show}">
    <h:form id="test1">
       <h:commandLink action="#{cartBean.foo}">link
          <f:param name="show" value="true"/>
       </h:commandLink> 
    </h:form>
</c:if>
Topera
  • 12,223
  • 15
  • 67
  • 104
0

IMPROVED (and tiny) WORKARROUND:

Change only XHTML:

Before:

<c:if test="#{cartBean.itemsAdded}">
    <h:form id="test1">
        <h:commandLink action="#{cartBean.foo}">link</h:commandLink>           
    </h:form>
</c:if>

After:

<c:if test="#{cartBean.itemsAdded || params['show']}">
    <h:form id="test1">
       <h:commandLink action="#{cartBean.foo}">link
          <f:param name="show" value="true"/>
       </h:commandLink> 
    </h:form>
</c:if>
Topera
  • 12,223
  • 15
  • 67
  • 104