0
votes

Here is the situation:

  1. I have a component, whose value is a property of my ViewScoped bean, which gets a FacesMessage generated for it do to some error when the form is first submitted
  2. On a subsequent user action, a h:commandlink is clicked, which uses f:ajax, and its actionlistener sets the component to no longer be rendered
  3. Upon receiving the reponse, the component is no longer rendered (as expected), but the FacesMessage for it still remains and is displayed

I am using Mojarra JSF 2.1, and IceFaces 3.0 - although this example and the problematic behavior are seen using only standard JSF components. Here is a small example that demonstrates the behavior:

test.xhtml

<h:form id="testform">
    <h:message for="tv"/>
    <h:inputText id="tv" value="#{testBean.testVal}" rendered="#{testBean.testValRendered}" required="true" />
    <h:commandButton value="Submit"/>
            <h:commandLink actionListener="#{testBean.toggleTestVal}" value="Toggle input">
        <f:ajax execute="@this" render="@form"/>
    </h:commandLink>
</h:form>

Bean code

@ViewScoped
@ManagedBean(name = "testBean") 
public class TestBean {

    private String testVal;
    private boolean testValRendered;

    public TestBean() {
        testValRendered = true;
    }

    public String getTestVal() {
        return testVal;
    }

    public void setTestVal(String testVal) {
        this.testVal = testVal;
    }

    public boolean isTestValRendered() {
        return testValRendered;
    }

    public void setTestValRendered(boolean testValRendered) {
        this.testValRendered = testValRendered;
    }

    public void toggleTestVal(ActionEvent ae) {
        testValRendered = !testValRendered;
    }
}

If I change the h:commandLink so that it does not use f:ajax, and set immediate='true' on it instead, then the message is removed properly. While this may work in some cases, I would like to understand why using f:ajax to render things as I have in my example does not work. Thanks.

1

1 Answers

1
votes

The input component is submitted, processed and validated before its rendering condition has been toggled. The <h:message> isn't aware that the associated input component is not rendered. You'd like to check the very same rendering condition on the <h:message> as well:

<h:message for="tv" rendered="#{testBean.testValRendered}" />
<h:inputText id="tv" ... rendered="#{testBean.testValRendered}" />