0

I have a p:dialog with a text input. When saving, the entered value is passed to an external service which may either accept or reject it. The text input has a validator, but that validator can only check so much. In particular, it does not know the external service's state. It cannot make a call to that service either cause between the checking time and saving time the input may become invalid.

So far, I have a <h:messages> in the page and in the popup. The popup is in its own form. The external service's validation error appears in the page's <h:messages> as the popup is closed because as a workaround I added the page's messages to the command button's update attribute. The popup's p:commandButton uses ajax='true' and a check for validation errors (oncomplete="if (arg &amp;&amp; !arg.validationFailed) PF('popup').hide()") as explained in another post. It looks like validation is finished and there are no errors, so the popup closes and the button's actionListener runs to push the input to the external service, and then the error is returned from the service.

I understand that validating in a setter or listener is an anti-pattern, but I don't see a way around it here. It's not so much validating anyway, it's more a "take this" and being prepared to receive an error for it.

I tried opening the popup again from the listener but that did not open the dialog.

<h:form id="Form">
    <h:messages id="pageErrors"/> <!-- external service error shows up here -->
<h:form>

<h:form>
    <p:dialog widgetVar="popup">
        <h:messages id="popErrors"/> <!-- I'd like to show the external service error here -->
        <p:inputTextarea id="it" required="true"/>
        <!-- required works as expected: error in the popup when nothing is entered, popup remains open -->
        <p:commandButton value="Save it" ajax="true" update="popErrors Form:pageErrors"
            oncomplete="if (args &amp;&amp; !args.validationFailed) PF('popup').hide();"
            actionListener="#{bean.saveIt}"/>
    </p:dialog>
</h:form>

And the actionListener:

public void saveIt(@SuppressWarnings("unused") ActionEvent e) {
    String error = extService.saveIt(it);
    if (error != null) {
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(error)); // gets the error in the page's messages
        facesUtil.showDialog("popup");
    }
}

How can I keep this dialog open when the actionListener detects an error from the external service?

Robert
  • 7,394
  • 40
  • 45
  • 64
  • Tried onsuccess instead of oncomplete? and/or closing it from the actionListener? – Kukeltje Jun 30 '17 at 15:37
  • Have a look into this answer, it might help you, because in your case validationFailed is not the answer, you need your own error handling https://stackoverflow.com/a/19834249/833031 – Hatem Alimam Jun 30 '17 at 15:42

1 Answers1

1

If I understand the problem this works for me:

update="popErrors :Form:pageErrors"

and

FacesContext.getCurrentInstance().validationFailed();

right after you add the message.

Adding a FacesMessage to the response is not the same as that the validation has failed. If you validate yourself, you must manually tell the framework if it failed.

You could also add your own callback parameter as Hatem suggests, but to my knowledge there is no problem reusing validationFailed.

Jaqen H'ghar
  • 4,305
  • 2
  • 14
  • 26