Проверка диапазона дат

Я хочу сравнить две даты (StartDate и EndDate) и проверить, находится ли одна перед другой. Самое простое решение - просто сделать это на подложке и" коротком замыкании " метода.

однако эта проверка не происходит одновременно с другими проверками формы. Например, если у меня есть другое поле, которое требует проверки (помимо дат) и имеет недопустимый ввод, я получу сообщение только для этого конкретного поля. Только если другие поля действительны, я буду получите проверку даты на основе резервного компонента.

У кого-нибудь есть решение?

3 ответов


однако эта проверка не происходит одновременно с другими проверками формы.

метод действия резервного компонента действительно не предназначен для выполнения проверки ввода.


у кого-нибудь есть решение?

Используйте правильный инструмент для работы; использовать обычный Validator.

@FacesValidator("dataRangeValidator")
public class DateRangeValidator implements Validator {
    // ...
}

проверка нескольких входных значений с одного валидатор в свою очередь, однако, действительно история отдельно. В принципе, вы должны захватывать / передавать другой компонент или его значение в validate() реализация метода. В простейшей форме вы можете использовать <f:attribute> для этого. Предполагая, что вы используете <p:calendar> чтобы выбрать даты, вот конкретный пример начала:

<p:calendar id="startDate" binding="#{startDateComponent}" value="#{bean.startDate}" pattern="MM/dd/yyyy" required="true" />
<p:calendar id="endDate" value="#{bean.endDate}" pattern="MM/dd/yyyy" required="true">
    <f:validator validatorId="dateRangeValidator" />
    <f:attribute name="startDateComponent" value="#{startDateComponent}" />
</p:calendar>

(обратите внимание на binding атрибут, он делает компонент доступным в области EL точно по заданному имени переменной; также обратите внимание, что этот пример как-есть и что вы абсолютно не должны привязывать его к свойству bean!)

здесь dateRangeValidator выглядит так:

@FacesValidator("dateRangeValidator")
public class DateRangeValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if (value == null) {
            return; // Let required="true" handle.
        }

        UIInput startDateComponent = (UIInput) component.getAttributes().get("startDateComponent");

        if (!startDateComponent.isValid()) {
            return; // Already invalidated. Don't care about it then.
        }

        Date startDate = (Date) startDateComponent.getValue();

        if (startDate == null) {
            return; // Let required="true" handle.
        }

        Date endDate = (Date) value;

        if (startDate.after(endDate)) {
            startDateComponent.setValid(false);
            throw new ValidatorException(new FacesMessage(
                FacesMessage.SEVERITY_ERROR, "Start date may not be after end date.", null));
        }
    }

}

если вы используете JSF utility library OmniFaces, тогда вы также можете просто использовать его <o:validateOrder> компонент. Требование может быть достигнуто следующим образом без необходимости пользовательского проверяющего элемента:

<p:calendar id="startDate" value="#{bean.startDate}" pattern="MM/dd/yyyy" required="true" />
<p:calendar id="endDate" value="#{bean.endDate}" pattern="MM/dd/yyyy" required="true" />
<o:validateOrder components="startDate endDate" />

Читайте также:


Если вы используете PrimeFaces, которые могут ограничить минимальную и максимальную даты. пользователь не смог выбрать больший диапазон это пример:

<p:calendar id="startDate" value="#{bean.startDate}" maxdate="#{bean.endDate}">
     <p:ajax event="dateSelect" update="endDate"/>
</p:calendar>
<p:calendar id="endDate" value="#{bean.endDate}" mindate="#{bean.startDate}" disabled="#{empty bean.startDate}">
      <p:ajax event="dateSelect" update="startDate"/>
 </p:calendar>

поскольку решение BalusC работает только в том случае, если у вас есть один диапазон дат для проверки в форме, вот улучшение, чтобы разрешить несколько проверок диапазона дат:

  • добавить <f:attribute> к компоненту календаря endDate, где вы указываете имя атрибута привязки к компоненту startDate:

    <f:attribute name="bindingAttributeName" value="startDateComponent" />
    
  • затем в валидаторе:

    String startDateBindingAttrName = (String) component.getAttributes().get("bindingAttributeName");
    UIInput startDateComponent = (UIInput) component.getAttributes().get(startDateBindingAttrName);