When validation fails, I want to submit the form nevertheless by ignoring the invalid fields in a second submit. The isolated problem is as follows:
My form consists of two required inputs foo
and bar
, which are additionally validated in a h:hiddenInput
and a custom validator named MyValidator
, which for example ensures the inequality of the inputs. If MyValidator
fails, I instead render another submit button that skips the h:hiddenInput
and its validator by processing only the inputs foo
and bar
.
<h:form>
<h:panelGroup layout="block" id="fooBarWrapper">
<p:inputText value="#{myControl.foo}" binding="#{foo}" required="true"/>
<p:inputText value="#{myControl.bar}" binding="#{bar}" required="true"/>
</h:panelGroup>
<h:inputHidden validator="myValidator" binding="#{myValidation}">
<f:attribute name="foo" value="#{foo}"/>
<f:attribute name="bar" value="#{bar}"/>
</h:inputHidden>
<p:messages/>
<p:commandButton action="#{myControl.doSomething()}" value="Do something"
process="@form" update="@form"
rendered="#{myValidation.valid}"/>
<p:commandButton action="#{myControl.doAnotherThing()}" value="Do another thing"
process="fooBarWrapper" update="@form"
rendered="#{not myValidation.valid}"
oncomplete="if (!args.validationFailed) { console.log('valid'); }"/>
</h:form>
with
@Named
@FacesValidator("myValidator")
public class MyValidator implements Validator {
@Override
public void validate(FacesContext ctx, UIComponent component, Object value) throws ValidatorException {
String foo = (String) ((UIInput) component.getAttributes().get("foo")).getValue();
String bar = (String) ((UIInput) component.getAttributes().get("bar")).getValue();
if (foo != null && bar != null && foo.equals(bar)) {
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Foo and bar must not be equal", ""));
}
}
}
and
@Named
@ViewScoped
public class MyControl implements Serializable {
private String foo;
private String bar;
public void doSomething() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Did something"));
}
public void doAnotherThing() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Did another thing"));
}
...
}
However, the action of the second button is not called, although MyValidator
is now skipped as expected. Interestingly, PrimeFaces args.validationFailed
indicates that the validation was successful.
Can anyone explain, why #{myControl.doAnotherThing()}
is not called, although no validation seems to fail?