一起验证两个inputText字段时出错 [英] Error validating two inputText fields together

查看:72
本文介绍了一起验证两个inputText字段时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含两个输入字段的表单,必须一起进行验证.我以 BalusC教程为起点. >

要求是逻辑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表示:

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

我不确定我是否可以使用此方法而不会在以后出现问题.

所以我的问题是:

此问题的原因是什么?

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

解决方案

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

但是,您的特殊情况令我震惊.我可以在Tomcat 7.0.11上使用Mojarra 2.0.4复制此问题. getValue()返回模型值而不是组件值.我不确定这是JSF2中的bug还是新东西,但是我确信它在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();

        // ...
    }

}

I have a form with two input fields that have to be validated together. I used this BalusC tutorial as starting point.

The requirement is a logical XOR: one of the fields must be filled but not both together.

This works fine for all cases except this one:

1) Fill the first field and let the second blank

2) Move to the next page (values get saved)

3) Go back to the first page, delete first field and fill second field.

Then I get the error message from my validator ("Do not fill both fields") although I deleted the first.

Here is the code:

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

Debugging this case reveals that the line

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

still holds the old value and not the new.

I tried to use getSubmittedValue() instead of getValue() and this works. But javadoc for this method says:

This method should only be used by the decode() and validate() method of this component, or its corresponding Renderer.

I am not sure if I can use this method without running in problems later.

So my questions are:

What is the reason for this issue?

Is using getSubmittedValue() instead of getValue() a real solution?

解决方案

This does not solve the problem. If you test getSubmittedValue(), then the validation will (incorrectly) pass when you fill both fields. In JSF, input components are validated in the order as they appear in the component tree. When a component is successfully been converted/validated, then the submitted value is set to null and the value is set with the converted/validated submitted value.

However, your particular case strikes me. I can replicate this problem with Mojarra 2.0.4 on Tomcat 7.0.11. The getValue() returns the model value instead of the component value. I'm not sure if that's a bug or new in JSF2 or something, I am however confident that it has worked that way in JSF 1.x. I believe this is related to changes with regard to the new JSF2 state management. I have to verify the one and other first (and probably also rewrite the multiple field validation blog article).

As another solution you could add a <h:inputHidden> before the two components as follows so that you can utilize getSubmittedValue() the right way:

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

with

@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();

        // ...
    }

}

这篇关于一起验证两个inputText字段时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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