2012-04-04 3 views
10

Ich nahm die folgende BalusC kickoff example und änderte es ein bisschen, indem ich eine Senden-Schaltfläche und zusätzliche h: messages hinzufügte und die f:ajax aus der h:inputSecret's entfernte (entfernt die f:ajax Ursache aus irgendeinem Grund, wenn ich die erste verlassen h:inputSecret zeigt es sofort "Wert ist erforderlich" Fehler für die zweite h:inputSecret - aber der Benutzer haben nicht die Chance, es einzugeben ... < - eine andere Zukunft ? Frage :))Wie kann ich ValidatorException anzeigen und Required = "true" des gleichen Eingabefeldes in verschiedenen Nachrichtenelementen

OK, lange Geschichte kurz zu machen:

Ich versuche herauszufinden, wie die Validierungsfehler in Bezug auf die beiden Passwortfelder (die Passwörter sind nicht gleich) in den globalen h: Nachrichten und nicht in den einzelnen h: Nachricht der Passwortfelder ich tun will, dass die erforderliche = "wahr" wird in der <h:message von jedem Feld angezeigt werden ...

Aber jetzt die Validierung Nachricht (ausgelöst von meiner Ausnahme) und die erforderlichen = "wahr" werden an der gleichen Stelle angezeigt Hier

ist der 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" /> 

Und zusätzliche h:commandButton mit h:messages unter diesem 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"/> 
@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.")); 
     } 
    } 

} 

Auch

Dank voraus,

Solution (Dank BalusC)

geändert

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

zu

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

und

String confirm = (String) component.getAttributes().get("confirm"); 

in

UIInput confirmPasswordComponent = (UIInput) component.getAttributes().get("confirm"); 
String confirm = (String) confirmPasswordComponent.getSubmittedValue(); 

und

throw new ValidatorException(new FacesMessage("Passwords are not equal.")); 

in

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

Antwort

8

Wenn ein Validator auf einer bestimmten Komponente wirft ein ValidatorException, dann seine FacesMessage wird automatisch mit dem Bauteil, auf dem in Verbindung gebracht werden der Validator aufgerufen wird.

Sie müssen die FacesMessage auf einer null Client-ID manuell hinzufügen, sodass sie in <h:messages globalOnly="true"> endet. Sie müssen auch validationFailed() unter FacesContext manuell festlegen, damit JSF die Modellwerte weder aktualisiert noch die Aktion aufruft.Bei Bedarf (obwohl empfohlen) müssen Sie die Komponenten auch manuell als ungültig markieren, damit alle geeigneten Listener/tree-visitors (z. B. zur Hervorhebung) dies berücksichtigen.

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. 
} 

By the way, das OmniFaces Projekt hat eine <o:validateEqual> Komponente, die diese weniger langweilig machen sollte. Siehe auch showcase example.

+0

Sie müssten es als Komponente übergeben und nicht als übergebenen Wert in f: attribute. Wie? – abbas

Verwandte Themen