java PrimeFaces 日历接受无效日期作为输入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13763717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 13:54:15  来源:igfitidea点击:

PrimeFaces calendar accepts invalid dates as input

javavalidationjsfprimefacescalendar

提问by JonnyIrving

The problem I am having is with the PrimesFaces 3.4.1 calendar. When using the popup date picker activated either through the button or on input field focus you can only select valid dates which work fine, happy days!

我遇到的问题是 PrimesFaces 3.4.1 日历。当使用通过按钮或输入字段焦点激活的弹出日期选择器时,您只能选择工作正常的有效日期,快乐的日子!

The issues comes when you manually add a date into the input field, if you add an invalid date the PrimeFaces calendar component takes its best guess at converting this into a valid date and then sending it, meaning that back-end validation is a no go. Some interesting translations below:

当您在输入字段中手动添加日期时会出现问题,如果您添加无效日期,PrimeFaces 日历组件会最好地猜测将其转换为有效日期然后发送,这意味着后端验证是行不通的. 以下是一些有趣的翻译:

  • 30/02/2012 becomes 2/6/2014
  • 322/05/2012 becomes 5/10/2038
  • 01/14/2012 becomes 4/1/2012
  • 30/02/2012 变成 2/6/2014
  • 322/05/2012 变成 5/10/2038
  • 01/14/2012 变成 4/1/2012

To recreate this madness have a look at the PrimeFaces Calendar Showcase.

要重现这种疯狂,请查看PrimeFaces 日历展示

I have seen solution around using the readOnlyInput='true'attribute but that only seems to prevent letters being entered in the field not number or slashes. Below is one instance of the calendar I have implemented:

我已经看到了使用该readOnlyInput='true'属性的解决方案,但这似乎只能防止在字段中输入字母而不是数字或斜线。以下是我实施的日历的一个实例:

<p:calendar id="fldDateOfBirth"
            value="#{pc_CreateUser.user.dateOfBirth}"
            binding="#{pc_CreateUser.dobComp}"
            navigator="true"
            pattern="dd/MM/yyyy"
            maxlength="10"
            yearRange="-100"
            validator="#{pc_CreateUser.validateDOB}"
            title="#{msg.user_date_format_default_tip}"
            converterMessage="#{msg.user_error_dob_invalid}"
            readOnlyInput="true"
            showOn="button" />

Solution wise I am open to any suggestions:

明智的解决方案我愿意接受任何建议:

  1. Is this a common issues in PrimeFaces? Is there a trick I can use to fix it?
  2. Could I use JavaScript to validate the date before it's sent or to block all user input entirely?
  3. Anything else I haven't thought of!
  1. 这是 PrimeFaces 中的常见问题吗?有什么技巧可以解决吗?
  2. 我可以使用 JavaScript 在发送日期之前验证日期或完全阻止所有用户输入吗?
  3. 还有什么是我没想到的!

Thanks in advance, this has been causing me issues for weeks!

提前致谢,这已经给我带来了几个星期的问题!

回答by BalusC

The <p:calendar>uses under the covers SimpleDateFormatwhich in turn uses by default lenientparsing, causing the overflowed values to roll over into the next date metric level. E.g. 32 January would become 1 February, etc.

<p:calendar>封面下使用SimpleDateFormat其默认情况下又使用宽松的解析,导致溢出值,以滚动到下一个日期度量水平。例如,1 月 32 日将变成 2 月 1 日,等等。

In plain Java terms, this can be turned off by DateFormat#setLenient(), passing false. See also among others this question: validating a date using dateformat.

用简单的 Java 术语来说,这可以通过DateFormat#setLenient()、 传递来关闭false。另请参见这个问题:validating a date using dateformat

In JSF terms, you basically need to provide a custom converter which uses a non-lenient DateFormat. Fortunately, standard JSF already provides such one out the box in flavor of <f:convertDateTime>, so you could just make use of it directly.

在 JSF 术语中,您基本上需要提供一个使用非宽松DateFormat. 幸运的是,标准 JSF 已经提供了这样一种开箱即用的<f:convertDateTime>,因此您可以直接使用它。

<p:calendar ...>
    <f:convertDateTime pattern="dd/MM/yyyy" />
</p:calendar>

回答by Pravin

In faces-config.xml add this

在faces-config.xml 中添加这个

<converter>
    <converter-id>localDateConverter</converter-id>
    <converter-class>com.utility.LocalDateConverter</converter-class>
</converter>

In the above class i.e LocaldateConverter add this below code

在上面的类中,即 LocaldateConverter 添加下面的代码

/**
 * @param facesContext .
 * @param uiComponent .
 * @param input .
 * @return Object .
 */
@Override
public Object getAsObject(final FacesContext facesContext, final UIComponent   uiComponent, final String input) {
    if (StringUtils.isBlank(input)) {
        return null;
    }
    final String componentPattern = (String) uiComponent.getAttributes().get("datePattern");
    final String patternToUse = componentPattern != null ? componentPattern : CommonConstants.OUTPUT_DATE_FORMAT;
    try {
        final DateFormat fmt = new SimpleDateFormat(patternToUse);
        Date convertedDate = new java.sql.Date(fmt.parse(input).getTime());
        return convertedDate;
    } catch (Exception e) {
        throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Invalid Date Format", null));
    }
}

/**
 * @param facesContext .
 * @param uiComponent .
 * @param obj .
 * @return String .
 */
@Override
public String getAsString(final FacesContext facesContext, final UIComponent uiComponent, final Object obj) {
    if (obj==null) {
        return null;
    }
    final Date date = (Date) obj;
    return date.toString();
}