Wie kann ich ValidatorException und required = "true" für dasselbe Eingabefeld in verschiedenen Nachrichtenelementen anzeigen?

Ich habe folgendes genommenBalusC Kickoff Beispiel und modifizierte es ein wenig, indem es einen Submit-Button und zusätzliche h: messages hinzufügte und das entferntef:ajax von demh:inputSecret's (entfernte dief:ajax Grund aus irgendeinem Grund, wenn ich den ersten verlasseh:inputSecret Es wird sofort der Fehler "Wert ist erforderlich" für die Sekunde angezeigth:inputSecret - aber der Benutzer hat nicht die Möglichkeit, es einzutippen ... ??? <- eine weitere zukünftige Frage? :))

OK, um es kurz zu machen:

Ich versuche herauszufinden, wie die Überprüfungsfehler in Bezug auf die beiden Passwortfelder (dass die Passwörter nicht gleich sind) in den globalen h: Nachrichten und nicht in den einzelnen h: Nachrichten der Passwortfelder angezeigt werden können = "true" wird im angezeigt<h:message von jedem Feld ...

Aber im Moment werden die (von meiner Ausnahme ausgelöste) Bestätigungsnachricht und das erforderliche = "true" an derselben Stelle angezeigt

Hier ist der Code:

<code><h:outputLabel for="password" value="Password:" />
<h:inputSecret id="password" value="#{bean.password}" required="true">
    <f:validator validatorId="confirmPasswordValidator" />
    <f:attribute name="confirm" value="#{confirmPassword.submittedValue}" />
</h:inputSecret>
<h:message id="m_password" for="password" />

<h:outputLabel for="confirm" value="Password (again):" />
<h:inputSecret id="confirm" binding="#{confirmPassword}" required="true">
</h:inputSecret>
<h:message id="m_confirm" for="confirm" />
</code>

Und zusätzlichh:commandButton mith:messages unter diesem Code:

<code><h:commandButton value="doSomething" action="#{myBean.myAction}">
    <f:ajax execute="password confirm" render="m_password m_confirm"></f:ajax>
</h:commandButton>
<h:messages globalOnly="true" styleClass="validation_value_required"/>
</code>
<code>@FacesValidator("confirmPasswordValidator")
public class ConfirmPasswordValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        String password = (String) value;
        String confirm = (String) component.getAttributes().get("confirm");

        if (password == null || confirm == null) {
            return; // Just ignore and let required="true" do its job.
        }

        if (!password.equals(confirm)) {
            throw new ValidatorException(new FacesMessage("Passwords are not equal."));
        }
    }

}
</code>

Ebenfalls

Danke im voraus

Lösung (Dank an BalusC)

geändert

<code><f:attribute name="confirm" value="#{confirmPassword.submittedValue}" />
</code>

zu

<code><f:attribute name="confirm" value="#{confirmPassword}" />
</code>

und

<code>String confirm = (String) component.getAttributes().get("confirm");
</code>

in

<code>UIInput confirmPasswordComponent = (UIInput) component.getAttributes().get("confirm");
String confirm = (String) confirmPasswordComponent.getSubmittedValue();
</code>

und

<code>throw new ValidatorException(new FacesMessage("Passwords are not equal."));
</code>

in

<code>context.addMessage(null, new FacesMessage("Passwords are not equal."));
context.validationFailed();
((UIInput) component).setValid(false);
confirmPasswordComponent.setValid(false);
return;
</code>

Antworten auf die Frage(1)

Lösung für das Problem

Validator auf eine bestimmte Komponente wirft einValidatorException, dann ist esFacesMessage wird automatisch der Komponente zugeordnet, auf der dieValidator wird aufgerufen.

Sie müssen das manuell hinzufügenFacesMessage auf einennull Client-ID, damit es in landet<h:messages globalOnly="true">. Sie müssen auch manuell einstellenvalidationFailed() aufFacesContext damit JSF weder die Modellwerte aktualisiert noch die Aktion aufruft. Falls erforderlich (obwohl empfohlen), müssen Sie die Komponenten auch manuell als ungültig markieren, damit alle geeigneten Listener / Baumbesucher (z. B. zum Hervorheben) dies berücksichtigen.

<code>if (!password.equals(confirm)) {
    context.addMessage(null, new FacesMessage("Passwords are not equal."));
    context.validationFailed();
    ((UIInput) component).setValid(false);
    confirmPasswordComponent.setValid(false); // You'd need to pass it as component instead of as its submitted value in f:attribute.
}
</code>

Übrigens, dieOmniFaces Projekt hat eine<o:validateEqual> Komponente, die dies weniger langweilig machen sollte. Siehe auchSchaufensterbeispiel.

 abbas19. Dez. 2017, 03:08
Sie müssen es als Komponente anstatt als übergebenen Wert in f: attribute übergeben. Wie?

Ihre Antwort auf die Frage