datepicker
输入允许用户从可自定义的日历中选择日期,并直接在输入中输入日期,支持完整的国际化。
FormKit 使用独特的遮罩解决方案,允许用户将日期输入到日期选择器输入中(同时将可用选项限制为仅有效值)或通过日历输入选择日期。
要在双重输入模式下显示占位符,您必须启用遮罩 overlay
。在启用 picker-only
时,不需要这样做。了解有关遮罩和覆盖层的更多信息。
您可以通过添加 picker-only
prop 禁用文本输入机制,并确保某人使用日期选择器对话框输入日期。在 picker-only
模式下,点击输入框将立即打开对话框。此外,不需要使用 overlay
来支持占位符:
日期选择器支持 Intl.DateTimeFormat
"样式日期",以及基于令牌的日期格式。要更改显示给用户的格式,请修改 format
prop。
如果您的受众是国际的,您应该考虑坚持使用"样式日期",因为它们是每个地区最自然的日期格式。日期选择器的默认格式为 long
。
format
属性可以接受一个简单的字符串,如 long
或 medium
,在这种情况下,它使用相应的 Intl.DateTimeFormat
dateStyle
。或者,您可以提供一个具有 date
和 time
属性及其各自 Intl.DateTimeFormat
样式的对象({ date: 'long', time: 'short' }
)。
使用 format
属性启用以下任何日期样式:
格式样式 | 示例 |
---|---|
full | Wednesday, March 1, 2023 , 2023年3月1日星期三 |
long | March 1, 2023 , 2023年3月1日 |
medium | Mar 6, 2023 , 2023年3月6日 |
short | 3/1/23 , 23/3/1 |
格式样式 | 示例 |
---|---|
long | 7:05:00 PM , 19:05:00 |
medium | 7:05:00 PM , 19:05:00 |
short | 7:05 PM , 19:05 |
您可以使用 format
属性显式设置一个令牌化的日期格式。令牌格式由一个包含任意字符和下表中的一个或多个字符串的字符串表示。
FormKit 通过 Intl.DateTimeFormat
接口自动根据当前 locale
国际化令牌。例如,对于 2000-01-01
,MMMM
令牌在 en
区域设置下会生成 January
,而在 zh
区域设置下会生成 一月
。
使用令牌时,有可能创建无法解析的日期。例如,如果您的输入仅显示星期几(dddd
)。您只能在 picker-only
模式下使用不可解析的日期格式。如果您希望允许用户输入日期,您的格式必须至少包括一个月、日和年令牌。
令牌 | 示例 | 描述 |
---|---|---|
YY | 99 , 23 , 00 | 2 位数年份 |
YYYY | 1999 , 2023 , 2100 | 4 位数年份 |
M | 1 , 12 | 月份 1-12 |
MM | 01 , 12 | 月份 01-12 |
MMM | 1月 , 2月 | 简短名称 1月-12月 |
MMMM | 一月 , 二月 | 完整名称 一月 - 十二月 |
D | 1 , 9 , 22 | 月份中的第几天 1-31 |
DD | 01 , 09 , 22 | 月份中的第几天 01-31 |
d | 一 , 二 , 三 , 四 , 五 , 六 , 日 | 单个数字天 "二" |
ddd | 周四 , 周六 | 简短的星期几名称 "周四" |
dddd | 星期一 , 星期二 | 完整的星期几名称 "星期三" |
H | 0 , 13 , 23 | 最小小时数字,24 小时制,0-23 |
HH | 00 , 13 , 23 | 2 小时数字,24 小时制,00-23 |
h | 12 , 1 , 11 | 最小小时数字,12 小时制,1-12 |
hh | 12 , 01 , 11 | 2 小时数字,12 小时制,01-12 |
m | 1 , 59 | 分钟 0-59 |
mm | 01 , 59 | 分钟 00-59 |
s | 1 , 59 | 秒 0-59 |
ss | 01 , 59 | 秒 00-59 |
a | 上午 , 下午 | 上午/下午 |
A | 上午 , 下午 | 上午/下午 |
尽管 FormKit 会自动国际化您的令牌 - 如果您的表单面向广泛的国际受众,请考虑使用日期样式而不是令牌,因为这会在许多地区产生更易读的日期。
要在格式中包含本身是标记(如 a
)的字母,可以在字符前使用反斜杠 \
转义这些标记:
日期选择器的日历弹出窗口有四个 "面板":
day
— 显示一个月的传统日历视图,每天都可以选择。month
— 显示一年的 12 个月。year
— 一次显示十年的年份。time
— 显示一天中的时间。当用户打开日期选择器的弹出窗口时,他们将看到一个或多个这些面板。您可以通过提供一个 sequence
prop 来修改显示给用户的面板以及这些面板应该显示的顺序。默认的 sequence
值是 ['day']
(允许您导航到 month
和 year
面板)。
例如,在选择生日时,先选择出生年份,然后选择月份,然后选择日期是自然的。sequence
prop 允许这种行为:
time
面板可用于允许用户选择一天中的特定时间。如果您选择包含时间的 format
(如 YYYY-MM-DD HH:mm
),您可能需要将 time
面板添加到序列中:
与所有输入一样,日期选择器的 value
既是由日期选择器生成的内容,也是读回到日期选择器中进行填充的内容。默认情况下,值的格式是 UTC 标准化的 ISO8601 字符串(示例:2014-11-27T03:59:00.000Z
)。但是,可以通过使用 value-format
prop 将此格式更改为上面列出的任何支持的日期样式或标记格式之一(#date-format)。
一个有效的问题是为什么不总是使用 ISO8601
?尽管它是处理日期的最流行方式 - 它既适用于机器又适用于人类阅读 - 但它对于人类阅读来说并不是非常易读。例如,如果您的表单向餐饮业务发送联系请求电子邮件,那么 ISO8601
可能不是最佳选择。
值格式必须包含重新构成日期对象所需的所有数据,至少包括月、日、年。如果您的输入向用户请求的信息在值格式中没有表示,那么这些详细信息将丢失。
要将日期样式用作值,只需将您要使用的样式传递给 value-format
属性:
值还可以使用格式化令牌以任意格式表示:
传递给日期选择器的值必须:
value-locale
中的 value-format
,或者Date
对象。尽管原生的 Date
对象始终被接受为日期选择器的有效输入,但它们将立即转换为指定的 value-format
。
value-format
Date
由于需要使用创建值时使用的相同区域设置来解析值的格式,因此建议在定义自定义 value-format
时始终指定 value-locale
。这样可以确保无论输入日期的用户的区域设置是什么,值都保持一致:
更改 value-locale
对所选日期的 timezone
没有影响。有关更多说明,请参阅下面的时区文档。
在任何软件环境中处理时间都是非常困难的,尤其是基于浏览器的 JavaScript。datepicker
提供了一些选项来帮助解决这些挑战。
为了在 JavaScript 中处理日期和时间,了解 Date
对象的基本知识是很有用的。JavaScript 中的日期对象基本上是一个 Unix 时间戳(自 1970 年 1 月 1 日 00:00:00Z
以来的毫秒数)。然而,它始终根据客户端的时间进行本地化。这种本地化以 UTC
的偏移量表示。您的浏览器当前时间是:
将偏移量应用于 "时钟时间",您将得到当前的 UTC 时间:
在日期选择器中使用 value-format
令牌时,这些令牌将使用客户端的时区。例如,如果您的格式请求 HH
令牌,它将返回:
将其与上述日期进行比较,您会发现它与本地时间的 hours
部分相同。为什么这很重要?请继续阅读。
让我们考虑一个位于阿姆斯特丹(UTC +100/+200
)的餐厅的预订应用。这是游客的热门目的地,他们经常在出行前几周就预订(在他们的祖国)。
默认情况下,日期选择器会询问游客他们希望预订的日期和时间,但(默认情况下)选择的是他们的当地时间,而不是阿姆斯特丹的时间。尽管 value-format
输出的是 UTC,但时间不会是阿姆斯特丹预期的预订时间(除非他们碰巧在同一时区)。
一般来说,有两种解决方案:
使用“不确定”时间(有时称为“墙上时间”)。不确定时间是没有特定关联到底层 Unix 时间戳的时间。例如,3 月 13 日下午 2 点
不是 UTC,也没有明确的偏移量。3 月 13 日下午 2 点
描述了一个不确定位置/时区的特定时间。只要您不在值中使用偏移量(Z
),您可以使用格式令牌(如 YYYY-MM-DD HH:mm
)来实现这一点。
只要后端能够将适当的时区或偏移量附加到这个不确定时间 2023-03-13 14:00 GMT+0100
,以得到适当的 UTC 时间(这个虚构的应用程序在其数据库中需要的),这对于我们的餐厅应用程序就可以工作。对于后端开发人员来说,剩下的挑战是知道应用于日期的偏移量,以确保它成为“阿姆斯特丹时间”(由于 Europe/Amsterdam
的夏令时,这个偏移量会根据一年中的时间而变化)。
timezone
属性或者,日期选择器的 timezone
属性将自动为您进行偏移校正。只需声明日期选择器为哪个地方选择时间 —— 在我们的示例中 timezone="Europe/Amsterdam"
。用户的体验不会有任何变化,但他们选择的时间将是目标时区的时间。一个位于 America/New_York
(+0400
)的用户,如果在日期选择器中选择 3 月 13 日下午 2 点
,将产生一个 UTC 值为 2023-03-13T13:00:00Z
,这是阿姆斯特丹的 2pm
。这允许您使用 UTC
格式简单地存储和提取日期。
默认情况下,当进行选择时,日期选择器使用客户端的本地时区。输出值由 value-format
确定(见上文)—— 默认情况下,这是一个 UTC
标准化的 ISO8601
字符串。然而,通过指定一个自定义格式,您可以实现一个“不确定”的时间(也称为“墙上时间”)。这是一个没有特定关联到给定时区的日期和/或时间。
例如,当您为手机设置一个 8:00 AM
的闹钟时,那个时间是“不确定”的,它与时区无关。如果您住在罗马,然后去东京,您的闹钟会在东京的 8:00 AM
响,就像它在罗马的 8:00 AM
一样。这是不可能表示为 UTC 的。
您可以通过在 value-format
中不提供时区或偏移信息来实现日期选择器的不确定时间 —— 解释日期的人需要添加这些信息。value-format
中的令牌总是输出本地客户端值 —— 通过将任何时区或偏移(Z
)数据从值中排除,它本质上是“不确定”的:
对于某些应用程序,需要选择给定位置的时间,这可能相当具有挑战性。为了帮助解决这个问题,日期选择器支持显式指定输入的timezone
。
timezone
属性允许您根据浏览器支持的IANA时区指定日期选择器的“位置”。当您希望允许用户选择一个给定地理位置的日期和时间时,这一点非常重要,无论客户端的位置如何。一些示例用例包括:
有很多时候timezone
不应该被使用(默认为客户端时间):
在下面的示例中,用户需要在国际航班后在印度加尔各答取一辆租赁汽车。用户查看他们的机票 - 航班到达加尔各答的时间为1:45 PM
。他们希望在45分钟后的2:30 PM
取车。无论用户从世界上的哪个地方预订行程,这些事实都是真实的。在这种情况下,我们应该将时区设置为Asia/Kolkata
。加尔各答的偏移量为+5:30
- 因此,在Kolkata
选择2:30 PM
相当于09:00 AM
UTC:
大多数浏览器都内置了一个完整的IANA数据库,内置在Intl.DateTimeFormat
中。这非常好,因为FormKit不需要将(相当广泛的)时区数据库发送到客户端的浏览器。然而,一些较旧的浏览器可能没有IANA数据库。可以通过使用polyfill.io和Intl.DateTimeFormat.~timeZone.all
轻松地填充这些数据。
通常需要在日期选择器中禁用特定日期。在日期选择器中禁用日期有三种方法:
min-date
- 一个属性,用于控制第一个可用日期是什么。max-date
- 一个属性,用于控制最后一个可用日期是什么。disabled-dates
- 一个属性,用于控制是否应禁用任意日期。任何被禁用的日期都不能在日期选择器的弹出窗口中选择,但是不可用的日期仍然可以作为初始值设置,或者通过输入(当它不处于picker-only
模式时)输入。为了处理这些边缘情况,日期选择器具有一个内置的验证规则(不能被禁用),确保只有有效的日期可以提交。验证规则的键是invalidDate
。
通常需要禁用早于特定日期的日期。例如,预订酒店房间只能在未来的日期进行。要做到这一点,请使用 min-date
属性,可以是与 ISO8601
兼容的字符串或原生 Date
对象:
要禁用给定日期之后的所有日期,请使用 max-date
属性。例如,生日选择器应该只允许过去的日期。要做到这一点,请使用 max-date
属性,可以是与 ISO8601
兼容的字符串或原生 Date
对象:
您可以同时使用 min-date
和 max-date
。这不仅会限制日期范围,而且在使用文本输入时,它还会将可用的年份限制为仅有效年份。
通常,我们的应用程序在禁用日期方面需要比 min-date
和 max-date
允许的更多粒度。日期选择器通过利用 disabled-days
属性允许进行细粒度控制。
disabled-days
属性期望一个传递了 2 个参数的函数:核心节点 和一个 Date
对象。函数的职责是返回一个布尔值,表示日期是否被禁用(true
表示禁用)。
disabled-days
属性取代了 min-date
和 max-date
—— 您可以通过访问 node.props.minDate
或 node.props.maxDate
重新实现基本功能。
请确保提供的函数快速且同步 —— 它将被频繁且重复地调用。例如,如果您需要从数据库获取信息,请在此函数之外执行,并使用此函数访问备忘结果。
通过键盘导航日历弹出窗口时,日期选择器不允许您选择禁用的日期。然而,如果一些可用日期被不可用日期“夹住”,这可能会令人烦恼,因为它会创建无法访问的区域。
为了使用户体验更好,日期选择器将自动向前或向后扫描(取决于所需的方向)以查找下一个可用的日期进行选择。扫描可用日期的最大天数由 maxScan
属性控制(默认为 7 天):
Prop | Type | 默认 | 描述 |
---|---|---|---|
date-format | string | D | 日历中月份日期的令牌格式。 |
disabled-days | function | min/max date logic | 传递核心节点和 `Date` 对象的函数,必须返回日期是否被禁用(`true` 表示禁用)。 |
format | string/object | date: 'long' | 在选择输入中显示给用户的格式。 |
max-date | Date | ISO8601 | none | 用户允许选择的最大日期。 |
max-scan | number | 7 | 通过键盘导航查找可用日期以跳转到的最大天数。 |
min-date | Date | ISO8601 | none | 用户允许选择的最早日期。 |
month-button-format | string | MMMM | 日历弹出窗口中月份面板按钮的日期格式令牌。 |
month-format | string | MMMM | 月份面板上每个月的日期格式令牌。 |
overlay | boolean | false | 是否显示遮罩层。在遮罩输入文档中阅读更多关于遮罩层的信息(在 pickerOnly` 模式下无效)。 |
picker-only | boolean | false | 是否允许通过文本输入输入日期。启用 picker-only 时,只能使用选择器选择日期。 |
show-months | number | 1 | 在弹出窗口的日期面板上渲染的月份数。 |
sequence | array | ['day'] | 当用户打开日期选择器日历视图时,引导用户的面板顺序。选项为 `year`、`month`、`day`、`time`。 |
value-format | string/object | ISO8601 | 作为输入值的格式。这可以与任何令牌格式、日期样式或 `ISO8601` 组合。 |
value-locale | string | `node.props.locale` | 用于 `valueFormat` 的区域设置。在 `valueFormat` 属性中使用格式令牌时,强烈建议设置显式 `valueFormat`。 |
week-start | number | 0 | 在 `day` 面板的日历上开始一周的日期。0-6,其中 0 = 星期日,6 = 星期六。 |
week-day-format | string | d | 用于渲染星期列标题的日期格式令牌。 |
year-format | string | YYYY | 用于在 `year` 面板中渲染年份的日期格式令牌。 |
显示 通用 props | |||
config | Object | {} | 提供给 input 的节点和此输入的任何后代节点的配置选项。 |
delay | Number | 20 | 在调度 commit hook 前,输入值的去抖动毫秒数。 |
dirtyBehavior | string | touched | 确定此输入的“dirty”标志设置方式。可以设置为 touched 或 compare — 默认为 touched ,性能更好,但无法检测表单是否再次匹配其初始状态。 |
errors | Array | [] | 要在此字段上显示的错误消息的字符串数组。 |
help | String | '' | 帮助文本与输入关联的文本。 |
id | String | input_{n} | 输入的唯一标识符。提供一个 id 还可以全局访问输入的节点。 |
ignore | Boolean | false | 防止将输入包含在任何父级(组、列表、表单等)中。在仅用于 UI 而不是实际值的情况下非常有用。 |
index | Number | undefined | 如果父级是列表,允许在给定索引处插入输入。如果输入的值未定义,它将继承该索引位置的值。如果它有一个值,它将在给定索引处将其插入到列表的值中。 |
label | String | '' | 与输入关联的 label 元素的文本。 |
name | String | input_{n} | 输入的名称,在数据对象中唯一标识。在一组字段中应该是唯一的。 |
parent | FormKitNode | contextual | 默认情况下,父级是包装组、列表或表单,但此属性允许显式分配父级节点。 |
prefix-icon | String | '' | 指定放置在 prefixIcon 部分的 图标。 |
preserve | boolean | false | 在输入卸载时,在父组、列表或表单上保留输入的值。 |
preserve-errors | boolean | false | 默认情况下,使用 setErrors 在输入上设置的错误会在输入时自动清除,将此属性设置为 true 可以保留错误,直到明确清除为止。 |
sections-schema | Object | {} | 一个包含部分键和模式部分值的对象,其中每个模式部分应用于相应的部分。 |
suffix-icon | String | '' | 指定放置在 suffixIcon 部分的 图标。 |
type | String | text | 要从库中渲染的输入类型。 |
validation | String, Array | [] | 要应用于输入的 验证 规则。 |
validation-visibility | String | blur | 确定何时显示输入的验证失败规则。有效值为 blur 、dirty 和 live 。 |
validation-label | String | {label prop} | 确定在验证错误消息中使用的标签,默认情况下,如果可用,则使用 label 属性,否则使用 name 属性。 |
validation-rules | Object | {} | 附加的自定义验证规则,可用于验证 prop。 |
value | Any | undefined | 为输入和/或其子元素提供初始值。不是响应式的。可以种子 整个组(表单)和列表。 |
您可以使用部分的 "key" 定位输入的特定部分,从而修改该部分的类、HTML(通过 :sections-schema
)或内容(通过插槽)。在此处阅读有关部分的更多信息。
当添加 overlay
prop 时,此部分位于 inner
部分内。
当日期选择器弹出窗口打开时,面板位于 inner
部分内的输入元素下方。
当日期选择器弹出窗口打开时,面板会出现在 inner
部分的输入元素下方。
当日期选择器弹出窗口打开时,面板会出现在 inner
部分的输入元素下方。
当日期选择器弹出窗口打开时,面板会出现在 inner
部分的输入元素下方。
Section-key | 描述 |
---|---|
calendar | 日历面板上日历的外围包装。 |
calendarHeader | 日历面板上标题栏的外围包装。 |
calendarWeeks | 日历面板上每行周的外围包装。 |
day | 日期的内容 — 默认包含数字日期。在此插槽/部分中,您可以使用 context.day (在 schema 中为 $day )获取给定日期的日期对象。 |
dayButton | 时间面板标题栏中的按钮,导航至日期面板。 |
dayCell | 日期部分的外围包装。在此插槽/部分中,您可以使用 context.day (在 schema 中为 $day )获取给定日期的日期对象。 |
daysHeader | 日期面板上标题栏的外围包装。 |
month | 在月份面板上渲染实际月份名称的部分。在此插槽/部分中,您可以使用 context.month (在 schema 中为 $month )获取给定月份的日期对象。 |
monthButton | 日期和时间面板标题栏中的按钮,导航至月份面板。 |
months | 月份面板上月份部分的外围包装。 |
monthsHeader | 月份面板上标题按钮(yearButton)的外围包装。 |
next | 面板标题栏中负责导航至下一个月或十年的按钮。 |
nextLabel | 负责渲染面板标题栏中下一个按钮文本内容的部分。 |
openButton | 负责打开选择器对话框的按钮。 |
overlay | 覆盖层的外部包装。覆盖层用于在文本输入模式下模拟文本输入中的文本,以便进行样式设置。 |
overlayChar | 包含类型为 char 的覆盖字符的部分 |
overlayEnum | 包含类型为 enum 的覆盖字符的部分 |
overlayInner | 覆盖部分内部的内部包装。 |
overlayLiteral | 包含类型为 literal 的覆盖字符的部分 |
overlayParts | 包含所有覆盖部分作为直接子元素的部分。 |
overlayPlaceholder | 包含类型为占位符的覆盖字符的部分。 |
panel | 围绕当前活动面板的包装。这将作为 panelHeader 的兄弟元素呈现。 |
panelHeader | 围绕每个面板标题栏的包装,面板的导航按钮位于此处。这是面板部分的兄弟元素。 |
panelWrapper | 围绕面板和 panelHeader 部分的包装,此部分负责显示或隐藏选择器对话框。 |
prev | 面板标题栏中负责导航至上一个月或十年的按钮。 |
prevLabel | 负责渲染面板标题栏中上一个按钮文本内容的部分。 |
time | 包含 timeInput 的时间面板。 |
timeHeader | 时间面板的面板标题栏,带有导航至年份、月份和日期面板的按钮。 |
timeInput | 负责设置所选日期时间的原生 HTML time 输入。 |
week | 日历面板上一行 7 天的包装。 |
weekDay | 负责在日历面板的日历标题栏中渲染一周中的某一天(M、T、W 等...)的单元格。 |
weekDays | 日历面板上日历标题栏中一周中的天数的包装元素。 |
year | 负责在年份面板上渲染可用年份的元素。 |
yearButton | 月份、日期和时间面板标题栏中的按钮,导航至年份面板。 |
years | 年份面板,负责一次渲染十年的年份。 |
yearsHeader | 年份面板上的面板标题栏,显示当前十年的年份范围。 |
显示 通用 section keys | |
outer | 最外层的包装元素。 |
wrapper | 标签和输入周围的包装器。 |
label | 输入的标签。 |
prefix | 默认情况下没有输出,但允许直接在输入元素之前放置内容。 |
prefixIcon | 输出在前缀部分之前放置一个图标的元素。 |
inner | 实际输入元素周围的包装器。 |
suffix | 默认情况下没有输出,但允许直接在输入元素之后放置内容。 |
suffixIcon | 输出在后缀部分之后放置一个图标的元素。 |
input | 输入元素本身。 |
help | 包含帮助文本的元素。 |
messages | 包装所有消息的容器。 |
message | 包含消息的元素(或多个元素) - 最常见的是验证和错误消息。 |