JSF 2.0: проверить равенство 2 полей InputSecret (подтвердить пароль) без написания кода? - PullRequest
6 голосов
/ 26 мая 2010

Я разрабатываю чистое приложение JavaEE6 с JSF 2.0 и Glassfish. Моя реализация JSF - это Primefaces (кроме Mojarra, предоставленной Glassfish).

Я хочу проверить, равны ли значения 2 полей пароля в форме JSF. С Seam есть аккуратный компонент <s:validateEquality for="pw1"/>. Я хочу сделать то же самое без Seam, просто используя JSF (или, возможно, компонент библиотеки JSF). До сих пор я видел только примеры, которые проверяют форму с помощью специального валидатора. Но я хотел бы сравнить поля без написания кода Java или кода Javascript. Это возможно?

Вот как это выглядит со швом:

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

Ответы [ 7 ]

6 голосов
/ 19 мая 2014

Вы можете использовать тег Primefaces очень простым способом:

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

<p:password id="repeated_password" value="#{bean.password}" />
6 голосов
/ 03 июня 2010

Модуль Seam3 Faces будет поддерживать «Проверку форм по всем полям» в своем предстоящем выпуске Alpha3.Это ваш лучший выбор для решения с минимальным кодом, см. Этот блог для ознакомления.

В качестве альтернативы я сделал это программно с помощью тега f: attribute для передачи clientId другогополе формы для пользовательского валидатора, затем с помощью UIComponent, переданного в пользовательский валидатор, получить доступ к другому файлу с идентификатором.

Вот файл 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>

Вот класс валидатора:

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."));
    }
}
}
4 голосов
/ 28 мая 2014

Если вы используете библиотеку утилит JSF OmniFaces , то вы можете использовать <o:validateEqual>. Это также позволяет установить пользовательское сообщение. витрина имеет живой пример, демонстрирующий общий вариант использования подтверждения пароля. Вам даже не нужен ajax для обновления модели перед вызовом валидатора (как это делает ваш собственный подход ).

Вот минимально необходимый код:

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

Код Java не требуется.

4 голосов
/ 20 августа 2011

Мне пришлось использовать смесь обоих ответов, чтобы добиться успеха.

Я использовал короткое решение ifischers, но поле моего бина-пароля было пустым.

Поэтому я использовал строки Брайана Литема, чтобы получить UIInput из контекста:

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);
    }
}
3 голосов
/ 04 июня 2010

Вот так я наконец и сделал, и мне нравится, потому что он короткий и легкий.Единственная проблема заключается в том, что он не может быть повторно использован, но так как мне нужно это только в одном случае, я скорее сохраняю несколько LOC и делаю это таким образом.Фрагмент с моей точки зрения:

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

My Backing Bean (только важная часть):

@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);
    }
  }
0 голосов
/ 27 июля 2012

Отредактировано : Перед прочтением, пожалуйста, подумайте, что это решение отлично работает, и ответ пришел с июля 2012 года, поэтому, пожалуйста, не голосуйте за меня только потому, что вам не понравилось. Мир изменился, и теперь у нас есть лучшие компоненты и решения.

Без решения я был вынужден провести валидацию безобразно (не рекомендуется). По крайней мере, это работает, пока я не нашел лучшее решение.

В методе, который возвращает действие, я проверяю оба значения, в случае разных значений добавляю сообщения об ошибках в контексте и возвращаю ноль в обработчик навигации.

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 - это просто класс, имеющий несколько общих методов, таких как "addMessages".

0 голосов
/ 24 марта 2012

Вы можете сделать это легко с Apache MyFaces ExtVal.

...