将两个inputText字段一起验证时出错

时间:2011-04-27 15:07:15

标签: validation jsf jsf-2

我有一个两个输入字段的表单,必须一起验证。我用这个BalusC tutorial作为起点。

要求是逻辑XOR:必须填写其中一个字段,但不能同时填充

这适用于除此之外的所有情况:

1)填写第一个字段并让第二个字段

2)移动到下一页(值保存)

3)返回第一页,删除第一个字段并填写第二个字段

然后我从验证器收到错误消息(“不要填写两个字段”),尽管我删除了第一个。

以下是代码:

<h:inputText id="bbvol" size="10" value="#{a6.behandlungsvolumen.wert}"
         required="#{empty param['Laborwerte:pvol']}">
     <f:convertNumber locale="de"/>
</h:inputText>

<h:inputText id="pvol" size="10" value="#{a6.plasmavolumen.wert}"
         required="#{empty param['Laborwerte:bbvol']}">
     <f:convertNumber locale="de"/>
     <f:validator validatorId="volumeValidator" for="pvol"/>
     <f:attribute name="bbv_value" value="Laborwerte:bbvol" />
</h:inputText>

VolumeValidator:

public class VolumeValidator implements Validator {

    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        // Obtain the client ID of the first volume field from f:attribute.
        String bbvolID = (String) component.getAttributes().get("bbv_value");
        // Find the actual JSF component for the client ID.
        UIInput bbvolInput = (UIInput) context.getViewRoot().findComponent(bbvolID);
        // Get its value, the entered value of the first field.
        Number bbvol = (Number) bbvolInput.getValue();
        // Get the value of the second field
        Number pvol = (Number) value;
        // Check if only one of the fields is set
        if (bbvol != null && pvol != null) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Do not fill both fields!", null));
        }
    }
}

调试此案例会显示该行

Number bbvol = (Number) bbvolInput.getValue();

仍然保留旧值,而不是新值。

我尝试使用getSubmittedValue()代替getValue()使用。但是这种方法的javadoc说:

  

此方法仅应由   这个的decode()和validate()方法   组件,或其对应的   渲染器。

我不确定我是否可以使用此方法而不会在以后遇到问题。

所以我的问题是:

这个问题的原因是什么?

使用getSubmittedValue()代替getValue()是真正的解决方案吗?

2 个答案:

答案 0 :(得分:3)

这不能解决问题。如果您测试getSubmittedValue(),那么当您填写两个字段时,验证将(错误地)通过。在JSF中,输入组件按照它们在组件树中的显示顺序进行验证。成功转换/验证组件后,提交的值将设置为null,并使用转换/验证的提交值设置该值。

然而,你的特殊情况让我感到震惊。我可以在Tomcat 7.0.11上使用Mojarra 2.0.4复制此问题。 getValue()返回模型值而不是组件值。我不确定这是JSF2中的错误或新内容,但我确信它在JSF 1.x中已经有了这种方式。我相信这与新JSF2状态管理的变化有关。我必须先验证其中一个(并且可能还要重写多字段验证博客文章)。

作为另一种解决方案,您可以在两个组件之前添加<h:inputHidden> ,如下所示,以便您可以正确使用getSubmittedValue()

<h:form id="form">
    <h:inputHidden value="true">
        <f:validator validatorId="xorValidator" />
        <f:attribute name="input1" value="form:input1" />
        <f:attribute name="input2" value="form:input2" />
    </h:inputHidden>
    <h:inputText id="input1" value="#{bean.input1}" required="#{empty param['form:input2']}" />
    <h:inputText id="input2" value="#{bean.input2}" required="#{empty param['form:input1']}" />
    <h:commandButton value="submit" action="#{bean.submit}" />
    <h:messages />
</h:form>

@FacesValidator(value="xorValidator")
public class XorValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        UIInput input1 = (UIInput) context.getViewRoot().findComponent((String) component.getAttributes().get("input1"));
        UIInput input2 = (UIInput) context.getViewRoot().findComponent((String) component.getAttributes().get("input2"));

        Object value1 = input1.getSubmittedValue();
        Object value2 = input2.getSubmittedValue();

        // ...
    }

}

答案 1 :(得分:1)

除了带有getValue()/ getSubmittedValue()的{feature | bug} - 2.x中的方法之外,您可以尝试使用RequiredIf-Annotation进行XOR验证:

@RequiredIf(validationErrorMsgKey = "requiredField", valueOf = { "pvol" } , is = RequiredIfType.empty ) private String bbvol;

@RequiredIf(validationErrorMsgKey = "requiredField", valueOf = { "bbvol" } , is = RequiredIfType.empty ) private String pvol;

这对我来说就像一个类似验证星座的魅力。