如何避免多次显示 FacesMessage?

How to avoid displaying of FacesMessage multiple times?

我需要为这个组件显示一个 FacesMessage,如下所示,

问题是它多次显示在 UI 上,如下所示,

其次,输入的日期是 40.06.2015,这是无效的,因此是 FacesMessage,但它被转换成了 10.07.2015。我不知道如何防止这种情况。非常感谢任何帮助。我知道可以使用 DateFormat class 上的 setLenient() 轻松处理它,但不知何故,在它对我可用之前,UI 组件将其转换为日期下个月。

附加到该组件的验证器如下:

那么,如何避免多次显示 "Please enter date in correct format"?

我想到了使用 h:message 而不是 h:messages,并且在验证器方法的 catch 块中是这样的

FacesContext.getCurrentInstance().addMessage("formId:aboveCompId", message);

但 UI 上没有显示任何内容。有什么建议吗?

这种方法至少有两个问题。

  1. 您正在将组件绑定到 bean 属性。症状表明该 bean 不在请求范围内。这是一个非常糟糕的主意。 UI 组件本质上是请求范围的,不应在更广泛的范围内绑定为 bean 的 属性,否则 JSF 将重用它们而不是创建新的。如果你继续这样做,所有标签处理程序(包括验证器绑定)将 运行 一遍又一遍地在同一个 UI 组件实例上跨越对同一 bean 的请求,因此在每次回发时累积(你会看到相同视图上每次回发的消息数量增加,这是由于将相同的验证器重新附加到相同的组件实例造成的)。

  2. 您在验证器中手动添加面孔消息,而不是在其中抛​​出包含面孔消息的 ValidatorException。因此,JSF 生命周期在验证阶段之后错误地继续,而没有按照规范中止它。

另请参阅:

  • How does the 'binding' attribute work in JSF? When and how should it be used?
  • Custom Validator, should I use FacesContext#addMessage() or throw ValidatorException?

回到具体的功能需求。

  1. 至于非宽松日期转换,直接使用<f:convertDateTime>即可。如果需要,可以通过输入组件的 converterMessage 属性自定义转换器消息。

  2. 至于日期范围验证,等到转换完成,然后抓取右边的Date作为value,然后与Date#before()或[=进行比较18=].

所以,简而言之,这应该为您完成:

private Date startDate;
private Date endDate;
<t:inputCalendar id="startDate" binding="#{startDateComponent}" value="#{bean.startDate}" 
    renderAsPopup="true" renderPopupButtonAsImage="true"
    popupDateFormat="dd.MM.yyyy" popupTodayDateFormat="dd.MM.yyyy"
    converterMessage="Please enter date in correct format"
>
    <f:convertDateTime pattern="dd.MM.yyyy" />
</t:inputCalendar>

<t:inputCalendar id="endDate" value="#{bean.endDate}"
    renderAsPopup="true" renderPopupButtonAsImage="true"
    popupDateFormat="dd.MM.yyyy" popupTodayDateFormat="dd.MM.yyyy"
    converterMessage="Please enter date in correct format"
>
    <f:convertDateTime pattern="dd.MM.yyyy" />
    <f:validator validatorId="dateRangeValidator" />
    <f:attribute name="startDateComponent" value="#{startDateComponent}" />
</t:inputCalendar>

其中 dateRangeValidator 是真实且可重复使用的 @FacesValidator,可以在下面的第二个“另请参阅”link 中找到。请注意,第一个组件绑定到视图并且 绝对不是 绑定到 bean,并且验证是 not 紧密耦合到支持 bean .

另请参阅:

  • PrimeFaces calendar accepts invalid dates as input
  • Date range validation