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}"
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:
- Commandlink is not being invoked
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>
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:
- Send a parameter in request (like show=true)
- 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>
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>
精彩评论