我们需要向用户呈现两个 p:calendar 组件,分别代表一个开始日期和结束日期。两个日期时间都有日期、小时和分钟。PrimeFaces 具有可用的完美mindate
、maxdate
、minHour
、maxHour
、minMinute
和minMinute
属性。
现在的要求是:
无法将开始日期时间设置为大于或等于结束日期时间的任何值。不可能将结束日期时间设置为小于或等于结束日期时间的任何值。
以下等式应该成立:
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>
这是一个示例性的最小/最大方法(结束日期的 mindate):
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,只要将结束时间调整为至少 12:35,就应该允许选择日历日期 2013-04-20。
但是 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
以便在更新期间调用相应的 getter(getSelectedBeginDate()
和+ 最小/最大限制器)。getSelectedEndDate
然而,在更新上放置一个@this
会混淆 p:calendar 组件,使时间滑块只能滑动一次。随后的滑块事件将被简单地忽略,表现为损坏。
Q的
- 您通常如何解决这个问题?
- 是用
p:remoteCommand
的方式来达到我们想要的吗?
可选问:
- 为什么没有实施 PrimeFaces p:calendar 来提供单个 minDateTime 和 maxDateTime,这可能会解决手头的问题?
我敢打赌,我描述的这种情况之前已经解决了。如果您能描述您设法解决此问题的方法(甚至分享部分解决方案),我将不胜感激。