У нас есть требование представить два компонента p: calendar пользователю, представляя каждую дату начала и окончания. Оба времени имеют даты, часы и минуты.
PrimeFaces имеет отличные атрибуты mindate
, maxdate
, minHour
, maxHour
, minMinute
и minMinute
.
Теперь требуется следующее:
Невозможно установить начальное значение datetime на значение, большее или равное концу datetime. Невозможно установить конец datetime на что-либо меньшее или равное концу datetime.
Следующее уравнение должно иметь значение:
begin datetime < end datetime
Теперь мы попробовали следующий JSF:
<p:calendar id="begin-date"
value="#{debugManager.selectedBeginDate}"
mindate="#{debugManager.minBeginDate}"
maxdate="#{debugManager.maxBeginDate}"
maxHour="#{debugManager.maxBeginHour}"
maxMinute="#{debugManager.maxBeginMinute}"
pattern="yyyy-MM-dd HH:mm"
showButtonPanel="true"
readonlyInput="true"
navigator="true"
showOn="button"
required="true">
<p:ajax event="dateSelect" update="end-date" />
</p:calendar>
<p:calendar id="end-date"
value="#{debugManager.selectedEndDate}"
mindate="#{debugManager.minEndDate}"
minHour="#{debugManager.minEndHour}"
minMinute="#{debugManager.minEndMinute}"
pattern="yyyy-MM-dd HH:mm"
showButtonPanel="true"
readonlyInput="true"
navigator="true"
showOn="button">
<p:ajax event="dateSelect" update="begin-date" />
</p:calendar>
Здесь примерный метод min/max (отзыв даты окончания):
public Date getMinEndDate()
{
return this.getSelectedBeginDate();
}
Как вы можете видеть, минимальная дата окончания - это текущая дата начала AJAX. Установка даты окончания корректно запрещает установку даты начала за датой окончания.
Проблемы начинаются с вовлечения времени в уравнение...
Поскольку интерфейс p: calendar имеет отдельные методы, bean должен предоставить логику:
public int getMinEndHour()
{
Date selectedBeginDate = this.getSelectedBeginDate();
Date selectedEndDate = this.getSelectedEndDate();
if ( selectedBeginDate != null && DateUtil.isSameDay( selectedBeginDate, selectedEndDate ) )
{
return DateUtil.getHourOf( selectedBeginDate );
}
return ComplianceConstants.DEFAULT_COMPLIANCE_CASE_MIN_END_HOUR;
}
В основном это говорит только о том, была ли установлена дата начала, и даты начала и окончания в настоящее время одинаковы, ограничить выбранный конечный час (minHour
конечной даты) до часа начала.
Операции:
Set the begin datetime to 2013-04-20 12:34 (legit)
Set the end datetime to 2013-04-22 00:00 (legit)
Теперь время для конечной даты будет установлено в 00:00, а выбор даты календаря 2013-04-20 должен быть разрешен до тех пор, пока время окончания будет каким-то образом скорректировано как минимум на 12:35.
Компонент p: calendar, однако, не может знать этого и сейчас
sets the end datetime to 2013-04-20 00:00 (legit, but false)
...
Теперь проблема заключается в том, что когда пользователь нажимает определенную новую дату окончания в календаре, атрибуты mindate/maxdate не могут ограничить пользователя ударом того же самого, что и дата начала. Если дата окончания время теперь до того, как то же самое время начала, мы ничего не можем с этим поделать (что неправильно).
Теперь проблема заключается в том, что пользователь может закрыть календарь и просто нажать кнопку отправки, чтобы вставить ложные данные в БД. Конечно, валидатор может/должен быть запущен, но нам нужно как-то добиться этого без валидатора.
То, что мы пытались сделать дальше, - исправить методы setSelectedBeginDate( Date selectedBeginDate )
и setSelectedEndDate( Date selectedEndDate )
, чтобы отрегулировать временные фрагменты java.util.Date
, если даты были в тот же день. Что-то вроде этого:
public void adjustSelectedEndDate()
{
if ( this.selectedEndDate != null )
{
this.log.infov( "adjustSelectedEndDate: b-hour = {0}, e-hour = {1}", DateUtil.getHourOf( this.selectedBeginDate ), DateUtil.getHourOf( this.selectedEndDate ) );
if ( DateUtil.isSameDay( this.selectedBeginDate, this.selectedEndDate ) &&
( DateUtil.getHourOf( this.selectedEndDate ) < DateUtil.getHourOf( this.selectedBeginDate ) ) ||
DateUtil.getHourOf( this.selectedEndDate ) == DateUtil.getHourOf( this.selectedBeginDate ) && DateUtil.getMinuteOf( this.selectedEndDate ) <= DateUtil.getMinuteOf( this.selectedBeginDate ) )
{
this.log.info( "Adjusting selected end date!" );
this.selectedEndDate = DateUtil.addOneMinuteTo( DateUtil.copyTime( this.selectedBeginDate, this.selectedEndDate ) );
}
}
}
Это потребовало, чтобы мы добавили @this
к атрибуту update
каждого p:calendar
, чтобы в процессе обновления вызывались соответствующие геттеры (getSelectedBeginDate()
и getSelectedEndDate
+ ограничители min/max).
Размещение @this
в обновлении, однако, смущает компоненты p: calendar, делая ползунки времени только скользящими один раз. Последующие события слайдера просто игнорируются, они ведут себя сломанно.
Q-х
- Как вы обычно подходите к решению этого вопроса?
- Использует
p:remoteCommand
способ достижения желаемого?
Необязательный Q:
- Почему не был реализован календарь PrimeFaces p: calendar для предоставления одного minDateTime и maxDateTime, что потенциально может решить проблемы?
Готов поспорить, этот сценарий, который я описал, уже был решен ранее. Я был бы очень признателен, если бы вы могли описать подход, который вам удалось решить (или даже частично разрешить).