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:
- getting the target composite
- traverse its children
- check for messages on each component and, if any, delete them (wouldn't know how, though ...)
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.