如何在不同的消息元素中显示相同输入字段的ValidatorException和required =“true”

时间:2012-04-04 08:24:53

标签: validation jsf jsf-2

我接受了以下BalusC kickoff example并通过添加提交按钮和其他h:消息以及从f:ajax删除h:inputSecret's来修改了一下(删除了f:ajax由于某种原因,当我离开第一个h:inputSecret时,它立即显示第二个h:inputSecret的“值是必需的”错误 - 但是用户没有机会输入它......? ?< - 另一个未来的问题?:))

好的,长话短说:

我正在试图找出如何在全局h:消息中显示关于密码字段(密码不相等)的验证错误,而不是在密码字段的单独h:消息中显示 我确实希望所需的=“true”将显示在每个字段的<h:message中......

但是现在验证消息(由我的例外引发)和required =“true”显示在同一个地方

这是代码:

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

1 个答案:

答案 0 :(得分:8)

如果特定组件上的Validator引发ValidatorException,则其FacesMessage将自动与调用Validator的组件相关联。

您需要在FacesMessage客户端ID上手动添加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>组件,这样可以减少繁琐。另请参阅showcase example