【问题标题】:Error validating two inputText fields together一起验证两个 inputText 字段时出错
【发布时间】:2011-08-13 23:03:14
【问题描述】:

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

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

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

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>

体积验证器:

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() 是一个真正的解决方案吗?

【问题讨论】:

    标签: validation jsf jsf-2


    【解决方案1】:

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

    但是,你的特殊情况让我印象深刻。我可以在 Tomcat 7.0.11 上使用 Mojarra 2.0.4 复制这个问题。 getValue() 返回模型值而不是组件值。我不确定这是否是 JSF2 中的错误或新问题,但我相信它在 JSF 1.x 中以这种方式工作。我相信这与新的 JSF2 状态管理的变化有关。我必须先验证一个和另一个(可能还要重写多字段验证博客文章)。

    作为另一种解决方案,您可以在以下两个组件之前添加&lt;h:inputHidden&gt; ,以便您可以正确使用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();
    
            // ...
        }
    
    }
    

    【讨论】:

    • 感谢 BalusC。我会试试这个并报告它是否适合我。这听起来像是一个老问题:“这是一个错误还是一个功能?” ;-)
    • @BalusC 抱歉打扰你,我试图通过在 jsf 2.0 中使用 bean 验证来做同样的事情,这是我在 SO stackoverflow.com/questions/14621337/… 上发布的问题的链接,如果你看看这个...问候
    【解决方案2】:

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

    @RequiredIf(validationErrorMsgKey = "requiredField", valueOf = { "pvol" } , is = RequiredIfType.empty ) 私有字符串 bbvol;

    @RequiredIf(validationErrorMsgKey = "requiredField", valueOf = { "bbvol" } , is = RequiredIfType.empty ) 私有字符串 pvol;

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

    【讨论】:

    • 感谢您的回答。有趣的方法。没听说过这个注释。谷歌说这是一个 MyFaces 扩展,对吧?
    • 是的,它包含在 myfaces-extval-property-validation-2.x.jar 中。不幸的是,几乎没有关于其用法的文档。 (至少我找不到任何...)。您还需要 myfaces-extval-core.jar。 (甚至可能是 persistence-api.jar)。
    猜你喜欢
    • 2015-10-22
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 2015-12-07
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    相关资源
    最近更新 更多