JSF 不支持跨字段验证,是否有解决方法? [英] JSF doesn't support cross-field validation, is there a workaround?

查看:26
本文介绍了JSF 不支持跨字段验证,是否有解决方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JSF 2.0 只允许您验证一个字段上的输入,例如检查它是否是特定长度.它不允许你有一个表格,上面写着输入城市和州,或者只输入一个邮政编码."

JSF 2.0 only allows you to validate the input on one field, like check to see if it's a certain length. It doesn't allow you to have a form that says, "enter city and state, or enter just a zip code."

你是如何解决这个问题的?我只对涉及 JSF 验证阶段的答案感兴趣.我对将验证逻辑放入托管 Bean 不感兴趣.

How have you gotten around this? I'm only interested in answers that involve the validation phase of JSF. I'm not interested in putting validation logic in Managed Beans.

推荐答案

迄今为止我见过并使用过的最简单的自定义方法是创建一个 字段,并带有 ,其中您将所有涉及的组件引用为 .如果你在待验证组件之前声明它,那么你可以通过UIInput#getSubmittedValue().

The easiest custom approach I've seen and used as far is to create a <h:inputHidden> field with a <f:validator> wherein you reference all involved components as <f:attribute>. If you declare it before the to-be-validated components, then you can obtain the submitted values inside the validator by UIInput#getSubmittedValue().

例如

<h:form>
    <h:inputHidden id="foo" value="true">
        <f:validator validatorId="fooValidator" />
        <f:attribute name="input1" value="#{input1}" />
        <f:attribute name="input2" value="#{input2}" />
        <f:attribute name="input3" value="#{input3}" />
    </h:inputHidden>
    <h:inputText binding="#{input1}" value="#{bean.input1}" />
    <h:inputText binding="#{input2}" value="#{bean.input2}" />
    <h:inputText binding="#{input3}" value="#{bean.input3}" />
    <h:commandButton value="submit" action="#{bean.submit}" />
    <h:message for="foo" />
</h:form>

(请注意隐藏输入上的 value=true";实际值实际上并不重要,但请记住,验证器不一定会被触发当它为 null 或为空时,取决于 JSF 版本和配置)

(please note the value="true" on the hidden input; the actual value actually doesn't matter, but keep in mind that the validator won't necessarily be fired when it's null or empty, depending on the JSF version and configuration)

@FacesValidator(value="fooValidator")
public class FooValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        UIInput input1 = (UIInput) component.getAttributes().get("input1");
        UIInput input2 = (UIInput) component.getAttributes().get("input2");
        UIInput input3 = (UIInput) component.getAttributes().get("input3");
        // ...
        
        Object value1 = input1.getSubmittedValue();
        Object value2 = input2.getSubmittedValue();
        Object value3 = input3.getSubmittedValue();
        // ...
    }

}

如果你声明了在待验证的组件之后,那么涉及到的组件的值已经被转换和验证了,你应该通过 获取它们UIInput#getValue() 或者 UIInput#getLocalValue()(如果 UIInput 不是 isValid()) 代替.

If you declare the <h:inputHidden> after the to-be-validated components, then the values of the involved components are already converted and validated and you should obtain them by UIInput#getValue() or maybe UIInput#getLocalValue() (in case the UIInput isn't isValid()) instead.

或者,您可以为此使用 3rd 方标签/组件.RichFaces 例如有一个 标签,Seam3 有一个 OmniFaces 有几个标准的<o:validateXxx> 组件,这些组件都在这里展示.OmniFaces 使用基于组件的方法,该方法在 UIComponent#processValidators().它还允许以这种方式自定义,以便实现上述目的,如下所示:

Alternatively, you can use 3rd party tags/components for that. RichFaces for example has a <rich:graphValidator> tag for this, Seam3 has a <s:validateForm> for this, and OmniFaces has several standard <o:validateXxx> components for this which are all showcased here. OmniFaces uses a component based approach whereby the job is done in UIComponent#processValidators(). It also allows customizing it in such way so that the above can be achieved as below:

<h:form>
    <o:validateMultiple id="foo" components="input1 input2 input3" validator="#{fooValidator}" />
    <h:inputText id="input1" value="#{bean.input1}" />
    <h:inputText id="input2" value="#{bean.input2}" />
    <h:inputText id="input3" value="#{bean.input3}" />
    <h:commandButton value="submit" action="#{bean.submit}" />
    <h:message for="foo" />
</h:form>

@ManagedBean
@RequestScoped
public class FooValidator implements MultiFieldValidator {

    @Override
    public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) {
        // ...
    }
}

唯一的区别是它返回一个 boolean 并且消息应该在 中指定为 message 属性.

The only difference is that it returns a boolean and that the message should be specified as message attribute in <o:validateMultiple>.

这篇关于JSF 不支持跨字段验证,是否有解决方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆