Вопрос: Как я могу отобразить ValidatorException и require = "true" того же поля ввода в разных элементах сообщений


Я принял следующее Пример запуска BalusC  и немного изменил его, добавив кнопку отправки и дополнительные сообщения h: и удалив f:ajax из h:inputSecret's (удалены f:ajax причина почему-то, когда я оставляю первый h:inputSecret он немедленно отображает ошибку «значение требуется» для второго h:inputSecret - но у пользователя нет возможности ввести его ... ??? <- еще один вопрос в будущем? :))

ОК, чтобы сделать длинный рассказ коротким:  

Я пытаюсь выяснить, как отображать ошибки проверки в отношении обоих полей пароля (что пароли не равны) в глобальных h: сообщениях, а не в отдельном h: сообщении полей пароля Я хочу, чтобы требуемое значение = "true" отображалось в <h:message каждого поля ...

Но прямо сейчас сообщение проверки (брошенное моим исключением) и требуемое = «истина» отображаются в одном и том же месте

Вот код:

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

И дополнительные h:commandButton с h:messages ниже этого кода:

<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."));
        }
    }

}

Также

Спасибо заранее,

Решение (спасибо BalusC)

изменено

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

в

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

а также

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

в

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

а также

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

в

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

10


источник


Ответы:


Если Validator на конкретном компоненте бросает ValidatorException, то его FacesMessage будет автоматически ассоциирован с компонентом, на котором Validator вызывается.

Вам необходимо вручную добавить FacesMessage на null идентификатор клиента, чтобы он оказался в <h:messages globalOnly="true">, Вам также необходимо установить вручную validationFailed() на FacesContext так что JSF не будет обновлять значения модели или не вызывать действие. Если необходимо (хотя и рекомендуется), вам также необходимо вручную пометить компоненты как недопустимые, чтобы все соответствующие слушатели / древовидные посетители (например, для выделения) учли это.

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

Кстати, OmniFaces  проект имеет <o:validateEqual> который должен сделать это менее утомительным. Смотрите также пример витрины ,


8