JSF 2.0: Valider l'égalité de 2 inputsecret Les champs (confirmer le mot de passe) sans écrire de code?

StackOverflow https://stackoverflow.com/questions/2909021

  •  04-10-2019
  •  | 
  •  

Question

Je développe une application pure JavaEE6 avec JSF 2.0 et Glassfish. Ma mise en œuvre de JSF est Primefaces (à côté fourni Mojarra par Glassfish).

Je veux vérifier si les valeurs de 2 champs de mot de passe sous une forme JSF sont égaux. Avec Seam, il y a le <s:validateEquality for="pw1"/> élément propre. Je veux faire la même chose sans couture, tout en utilisant JSF (ou peut-être un élément d'une bibliothèque JSF). Jusqu'à présent, je ne ai vu des exemples qui valident la forme avec un validateur personnalisé. Mais je voudrais comparer les champs sans écrire de code Java ou code Javascript. Est-ce possible?

Ce à quoi il ressemble avec Seam:

...
<h:inputSecret id="passwort" value="#{personHome.instance.password}" 
    redisplay="true" required="true">
  <f:validateLength minimum="8"/>
  <a:support event="onblur" reRender="passwortField" bypassUpdates="true" ajaxSingle="true" />
</h:inputSecret>
...    
<h:inputSecret id="passwort2" required="true" redisplay="true">
  <!-- find the JSF2.0-equivalent to this tag: -->
  <s:validateEquality for="passwort"/>
  <a:support event="onblur" reRender="passwort2Field" bypassUpdates="true" ajaxSingle="true" />
</h:inputSecret>
...
Était-ce utile?

La solution 5

Ceci est la façon dont je l'ai fait enfin, que je aime parce que c'est court et facile. Le seul problème est que ce n'est pas vraiment réutilisable, mais comme je l'ai seulement besoin ce dans un cas, je préfère économiser quelques LOC et le faire de cette façon. Extrait de mon point de vue:

<h:inputSecret id="password" value="#{personHome.person.password}">
  <f:ajax event="blur" render="passwordError" />
</h:inputSecret> 
<h:message for="password" errorClass="invalid" id="passwordError" />

<h:inputSecret id="password2" validator="#{personHome.validateSamePassword}">
  <f:ajax event="blur" render="password2Error" />
</h:inputSecret> 
<h:message for="password2" errorClass="invalid" id="password2Error" />

Mon Backing Bean (juste la partie importante):

@Named @ConversationScoped
public class PersonHome {
  private Person person;

  public Person getPerson() {
    if (person == null) return new Person();
    else return person;
  }

  public void validateSamePassword(context:FacesContext, toValidate:UIComponent, value:Object) {
    String confirmPassword = (String)value;
    if (!confirmPassword.equals(person.getPassword()) {
      FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Passwords do not match!", "Passwords do not match!")
      throw new Validatorexception(message);
    }
  }

Autres conseils

Le Seam3 Module Faces soutiendra "Renvoyez le formulaire champ de validation" dans sa version Alpha3 imminente. C'est votre meilleur pari pour une solution de code minimal, voir cette le blog pour un howto.

Sinon je l'ai fait ce programme en utilisant le f:. Balise d'attribut pour passer le clientId d'un autre champ de formulaire à un validateur personnalisé, puis en utilisant le UIComponent passé dans le validateur personnalisé pour accéder à l'autre déposée par id

Voici le fichier Facelet:

<h:outputLabel value="Enter your email address" rendered="#{!cc.attrs.registration.subRegistration}" />
<h:inputText label="Email" id="textEmail1" value="#{cc.attrs.registration.email}" rendered="#{!cc.attrs.registration.subRegistration}" required="true" maxlength="128" size="35"></h:inputText>
<h:message for="textEmail1" rendered="#{!cc.attrs.registration.subRegistration}"></h:message>

<h:outputLabel value="Re-enter your email address confirmation:" rendered="#{!cc.attrs.registration.subRegistration and cc.attrs.duplicateEmailRequired}" />
<h:inputText label="Email repeat" id="textEmail2" rendered="#{!cc.attrs.registration.subRegistration and cc.attrs.duplicateEmailRequired}" maxlength="64" size="35">
    <f:validator validatorId="duplicateFieldValidator" />
    <f:attribute name="field1Id" value="#{component.parent.parent.clientId}:textEmail1" />
</h:inputText>
<h:message for="textEmail2" rendered="#{!cc.attrs.registration.subRegistration and cc.attrs.duplicateEmailRequired}"></h:message>

Voici la classe validateur:

package ca.triumf.mis.trevents.jsf.validator;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

@FacesValidator(value="duplicateFieldValidator")
public class DuplicateFieldValidator implements Validator {

@Override
public void validate(FacesContext context, UIComponent component, Object value)
        throws ValidatorException {
    // Obtain the client ID of the first field from f:attribute.
    System.out.println(component.getFamily());
    String field1Id = (String) component.getAttributes().get("field1Id");

    // Find the actual JSF component for the client ID.
    UIInput textInput = (UIInput) context.getViewRoot().findComponent(field1Id);
    if (textInput == null)
        throw new IllegalArgumentException(String.format("Unable to find component with id %s",field1Id));
    // Get its value, the entered text of the first field.
    String field1 = (String) textInput.getValue();

    // Cast the value of the entered text of the second field back to String.
    String confirm = (String) value;

    // Check if the first text is actually entered and compare it with second text.
    if (field1 != null && field1.length() != 0 && !field1.equals(confirm)) {
        throw new ValidatorException(new FacesMessage("E-mail addresses are not equal."));
    }
}
}

Vous pouvez utiliser la balise Primefaces de cette façon très simple:

<p:password id="password" value="#{bean.password}" match="repeated_password" />

<p:password id="repeated_password" value="#{bean.password}" />

Je devais utiliser un mélange des deux réponses pour réussir.

J'ai utilisé ifischers solution courte mais mon champ de mot de passe de haricot était nulle.

J'utilisé les lignes de Brian Leathem pour obtenir le UIInput du contexte:

public void passwordValidator(FacesContext context, UIComponent toValidate, Object value) {

    UIInput passwordField = (UIInput) context.getViewRoot().findComponent("registerForm:password");
    if (passwordField == null)
        throw new IllegalArgumentException(String.format("Unable to find component."));
    String password = (String) passwordField.getValue();
    String confirmPassword = (String) value;
    if (!confirmPassword.equals(password)) {
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Passwords do not match!", "Passwords do not match!");
        throw new ValidatorException(message);
    }
}

Si vous utilisez la bibliothèque utilitaire JSF OmniFaces , vous pouvez alors utiliser <o:validateEqual> . Il permet également de définir un message personnalisé. vitrine a un exemple vivant démontrant la usecase commune de valider la confirmation de mot de passe. Vous ne même pas besoin ajax mettre à jour le modèle avant d'appeler le validateur (comme votre propre approche fait).

Voici le code minimum nécessaire:

<h:inputSecret id="password" value="#{personHome.person.password}" />
<h:message for="password" />

<h:inputSecret id="password2" />
<h:message for="password2" />

<o:validateEqual components="password password2" 
    message="Passwords do not match!" showMessageFor="password2" />

Non Java code nécessaire.

Vous pouvez le faire facilement avec Apache MyFaces ExtVal.

Edité : Avant de lire, s'il vous plaît, considérer que cette solution fonctionne parfaitement, et la réponse est à partir de Juillet 2012, alors s'il vous plaît ne me pas vers le bas vote juste parce que vous ne l'aimez pas. Le monde a changé et nous avons maintenant de meilleurs composants et solutions.

Sans solution, j'ai été forcé de faire la validation d'une manière laide (non recommandé). Au moins cela fonctionne jusqu'à ce que je trouve une meilleure solution.

Dans la méthode qui renvoie l'action, je vérifie les deux valeurs, en cas de valeurs différentes, ajouter des messages d'erreur sur le contexte et nulle de retour vers le gestionnaire de navigation.

package com.jsf.beans.user;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.html.HtmlInputSecret;

import org.apache.commons.lang.StringUtils;

import com.pichler.jsf.beans.base.JsfViewBean;

 @ManagedBean(name = "changePassword")
 @RequestScoped
 public class ChangePassword extends JsfViewBean {
private HtmlInputSecret inputSecret1, inputSecret2;

/**
 * @return the inputSecret1
 */
public HtmlInputSecret getInputSecret1() {
    return inputSecret1;
}

/**
 * @param inputSecret1
 *            the inputSecret1 to set
 */
public void setInputSecret1(HtmlInputSecret inputSecret1) {
    this.inputSecret1 = inputSecret1;
}

/**
 * @return the inputSecret2
 */
public HtmlInputSecret getInputSecret2() {
    return inputSecret2;
}

/**
 * @param inputSecret2
 *            the inputSecret2 to set
 */
public void setInputSecret2(HtmlInputSecret inputSecret2) {
    this.inputSecret2 = inputSecret2;
}

private String password1, password2;

public String alterar() {
    if (!StringUtils.equals(password1, password2)) {
        addErrorMessage(inputSecret1.getClientId(),
                "As senhas não coincidem");
        addErrorMessage(inputSecret2.getClientId(),
                "As senhas não coincidem");
        return null;
    }
    return null;
}

/**
 * @return the password1
 */
public String getPassword1() {
    return password1;
}

/**
 * @param password1
 *            the password1 to set
 */
public void setPassword1(String password1) {
    this.password1 = password1;
}

/**
 * @return the password2
 */
public String getPassword2() {
    return password2;
}

/**
 * @param password2
 *            the password2 to set
 */
public void setPassword2(String password2) {
    this.password2 = password2;
}

}

* JsfViewBean est juste une classe qui a des méthodes communes, comme "addMessages".

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top