Louise
Louise

Reputation: 1451

How to remove FacesMessage on non-processed component after ajax operation

My scenario is as follows: I have a form with three addresses, each as a composite component. Each address has a link to copy it from one of the other two. The link sets target and source address via f:setPropertyActionListener, then calls a Bean method to do the actual copying based on these parameters. The link has an f:ajax that only executes the source address and renders the target address. This way, users can copy even if other addresses on the page (e.g. the one they want to copy to) have validation errors. Since the target fields are potentially invalid (and thus marked red in my case), but are not processed during the Ajax request I use p:resetInput (Primefaces) to have them reset.

This is were my problem lies: The reset works fine in that it does remove the invalid status and styleClass. The field itself looks perfectly fine. However, the error message I attached to it is still visible and will only vanish on a refresh. I thought the reset + re-render would take care of this, but alas it doesn't.

My next attempt was to extend the copy method so that it will clear the list of messages at the FacesContext, but this won't work: When I actually reach my Bean method, it means that the current context passed validation (for the fields that are part of the execute) and thus has no messages.

So, the question is: Is there a way to access the previously attached messages of the not-processed components? Based on this answer I'm thinking something like:

But maybe I am thinking this wrong. I'm not sure if the messages are even still there or if this this is some sort of updating-the-view problem? In that case I would need to know how to also reset the input message components (currently render uses an enclosing h:panelGroup as target, which asfaik should properly re-render the messages, just like it does with the inputs ...)

Any help appreciated.


Reduced it to the following example:

test.xhtml

<h:inputText id="string1" value="#{testBean.string1}" style="#{component.valid ? '' : 'background-color:red;'}">
    <f:validateLength minimum="4" />
    <f:ajax render="@this msg1" />
</h:inputText>
<h:message id="msg1" for="string1" />
<br /><br/>

<h:inputText id="string2" value="#{testBean.string2}" style="#{component.valid ? '' : 'background-color:red;'}">
    <f:validateLength minimum="4" />
    <f:ajax render="@this msg2" />
</h:inputText>        
<h:message id="msg2" for="string2" /><br /><br/>

<h:commandButton actionListener="#{testBean.actionCopyString}" value="Click me">
    <f:ajax execute="string1" render="string2" />
    <p:resetInput target="string2" />
</h:commandButton>

TestBean

@ManagedBean(name = "testBean")
@ViewScoped
public class TestBean {
    private String string1;
    private String string2;
    // + getters + setters

    public void actionCopyString() {
    string2 = string1;
    }
}

Behavior

Enter a valid string into field one (at least four characters). Enter an invalid string into field two and tab or click out of it. The field turns red and a message shows up. Then click the button. The valid value is copied. Thanks to <p:resetInput> the field also is no longer red. However, the message still shows. Including it into the render attribute or re-rendering a container component around both input and message does not have an effect. My goal is to also have the message disappear after the copy operation finishes.

Upvotes: 2

Views: 1865

Answers (1)

Louise
Louise

Reputation: 1451

Solved it. As per BalusC's comments, using <p:resetInput> and re-rendering the message tag works perfectly fine per se.

The mistake was deep inside our setup. When the project began it used IceFaces as UI framework, which was set up by a former colleague. Due to some changing requirements we have recently switched to PrimeFaces. To my knowledge all references to the IceFaces jars and includes and whatnot had been removed - however, today I found some preferences that sill referred to IceFaces. So it turns out that due to distribution via SVN, all our machines were still running the library in the background without any page actually using it.

Apparently, some generated output of IceFaces clashes with that of PrimeFaces (from the effects I experienced probably some JavaScripts and theming-related styleClasses). Although now a few styles on my pages look a bit odd, p:resetInput suddenly works as intended - as well as some other components (p:growlfor example) that have not been working at all so far.

This just made my day! I really had no more clue what was going on, but this fixed four of my most mysterious bugs in one go ... Yay!

Thanks BalusC for having a look at it. I really really really appreciate your effort here. I always find your answers to my questions to be a great help, and even more so the dozens of answers to other people's questions that saved me from guessing around and provided good examples on how to do stuff. Huge distance-hug!

Upvotes: 1

Related Questions