Ошибка при проверке двух полей inputText вместе - PullRequest
2 голосов
/ 27 апреля 2011

У меня есть форма с двумя полями ввода , которые должны быть проверены вместе . Я использовал этот 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 для этого метода говорит:

Этот метод должен использоваться только decode () и validate () метод этого компонент или его соответствующий Renderer.

Я не уверен, что смогу использовать этот метод без проблем в дальнейшем.

Итак, мои вопросы:

В чем причина этой проблемы?

Является ли использование getSubmittedValue() вместо getValue() реальным решением?

Ответы [ 2 ]

3 голосов
/ 27 апреля 2011

Это не решает проблему.Если вы протестируете getSubmittedValue(), то проверка (неправильно) пройдет, когда вы заполните оба поля.В JSF входные компоненты проверяются в порядке их появления в дереве компонентов.Когда компонент успешно преобразован / проверен, то отправленное значение устанавливается равным null, а значение устанавливается вместе с преобразованным / проверенным отправленным значением.

Однако ваш конкретный случай поражает меня.Я могу повторить эту проблему с Mojarra 2.0.4 на Tomcat 7.0.11.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 голос
/ 28 июля 2011

Помимо {feature | bug} с методами getValue () / getSubmittedValue () - в 2.x, вы можете попробовать аннотацию RequiredIf для аннотации XOR:

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

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

Это работает для меня как очарование в подобном созвездии проверки.

...