☰
ToolJet Date Picker 组件实战:属性、事件、校验规则与源码实现解析
2026/10/18 21:12:32 网站建设 项目流程

ToolJet Date Picker 组件实战:属性、事件、校验规则与源码实现解析

【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet

本文基于 ToolJet 官方组件文档 datepicker.md 展开,系统讲解 Date Picker 组件的五大属性、On select 事件、自定义校验(Custom Validation)、通用配置与样式参数,并结合仓库中 组件注册配置、V2 实现 与 校验工具函数 等源码,说明每个属性在底层是如何生效的。读完本文,你可以完整掌握日期选择器的配置方式、动态表达式写法、日期禁用逻辑,以及 V2 版本新增的组件级动作(CSA)能力。

组件定位:从预定义集合中选择日期与时间

Date Picker 组件允许用户从一个预定义的集合(日历面板)中选择一个日期(可选地包含时间)值。它是 ToolJet 中处理表单日期输入的基础组件,常见于报表筛选、审批流程、日程管理等内部工具场景。

从源码结构看,当前仓库同时维护了两套配置:

  • Legacy 配置(datepicker.js):name: 'DatePickerLegacy',展示名为 "Date Picker (Legacy)",渲染组件为Datepicker,支持日期+时间混合选择;
  • V2 配置(datepickerV2.js):name: 'DatePicker',展示名即为 "Date Picker",是新建应用时拖入画布的实际组件,渲染组件为DatePickerV2。

下文以官方文档描述的属性与行为为主线,辅以两份配置和组件实现作为佐证。

属性(Properties)详解

文档定义的五个核心属性如下,结合 Legacy 配置中的默认值(datepicker.js)补充取值与默认行为:

属性说明默认值
Default value作为日期选择器的占位值。若用户未提供值,则使用默认值。默认值必须是符合format字段的String。例如 format 设为MM/YYYY时,默认值应写为04/2022。'01/01/2022'
Format控制输入框与解析所使用的日期格式,同样要求是字符串。'DD/MM/YYYY'
Enable time selection?开关,开启后允许选择时间。点击fx可动态设置为{{true}}或{{false}}。{{false}}
Enable date selection?开关,开启后允许选择日期。同样支持fx动态控制。{{true}}
Disabled dates指定一组禁用日期,这些日期无法被选中。默认值是一个String数组。{{[]}}

Default value 与 Format 的联动解析

在 Datepicker.jsx 中可以确认两者的联动关系:组件在defaultValue变化时,会用moment(defaultValue, selectedDateFormat)按format解析默认值,只有解析结果有效时才会写入组件内部状态,否则置为 null:

useEffect(() => { if (isInitialRender.current) return; const dateMomentInstance = defaultValue && moment(defaultValue, selectedDateFormat); if (dateMomentInstance && dateMomentInstance.isValid()) { setInputValue(dateMomentInstance.toDate()); } else { setInputValue(null); } }, [defaultValue]);

这意味着 Default value 的字符串必须严格匹配 Format,否则默认值会被静默丢弃。这也是文档强调“default value needs to be a String with respect to the format field”的实现依据。

当同时开启时间选择时,Legacy 组件会把显示格式拼接为`${format} LT`(即日期格式加 12 小时制时间),见 Datepicker.jsx:

const selectedDateFormat = enableTime ? `${format} LT` : format;

Disabled dates:禁用指定日期

文档给出的示例——禁用 1 月 9 日:

{{['09-01']}}

设置后用户无法再选中该日期。从源码看,组件会遍历数组,用moment(item, format)逐个校验:合法项转换为 Date 对象后传给react-datepicker的excludeDates属性,日历面板中这些日期即被禁用(Datepicker.jsx):

useEffect(() => { if (Array.isArray(disabledDates) && disabledDates.length > 0) { const _exluded = []; disabledDates?.map((item) => { if (moment(item, format).isValid()) { _exluded.push(moment(item, format).toDate()); } }); setExcludedDates(_exluded); } }, [disabledDates, format]);

由此可以推断出两点实践要点:

  1. 数组中每一项同样受format约束,格式写错会被静默忽略(isValid()为 false 则跳过);
  2. 由于disabledDates是fx 字段(type: 'code'),可以写入任意表达式,例如{{components.query1.response.map(d => d.date)}},实现从查询结果动态拉取禁用日期。

V2 版本:更多属性、校验与动作

当前新建应用拖入的 "Date Picker" 走的是 V2 配置(datepickerV2.js),它在文档所述属性之外扩展了:

  • Label(显示名,默认'Label')与Placeholder(默认'Select date');
  • customDateFormat:以可视化控件形式选择日期格式,而不是手填字符串;
  • Enable clear button(showClearBtn,默认{{false}}):有值时显示清空按钮;
  • Loading state / Visibility / Collapse when hidden / Disable:均支持 fx 动态控制;
  • Tooltip + Tooltip 格式(plainText / markdown / html 三选一)。

V2 的默认defaultValue依然是'01/01/2022'、dateFormat默认'DD/MM/YYYY',与 Legacy 保持一致,见 datepickerV2.js。

事件(Events)

为 Date Picker 添加事件的方式:点击组件句柄打开右侧属性栏,进入Events分区,点击+ Add handler。

事件说明
On select用户每次选中一个日期时触发。

文档提示可参考 Action Reference 了解全部动作能力。

在源码层面,Legacy 组件的触发点在 Datepicker.jsx:

const onDateChange = (date) => { setShowValidationError(true); setInputValue(date); fireEvent('onSelect'); };

即onChange时先重新计算校验状态、更新暴露变量,再调用fireEvent('onSelect')。V2 组件的触发链类似,但会同时写入 Unix 时间戳与展示时间戳两个内部状态(DatePickerV2.jsx):

const onDateSelect = (date) => { const selectedTime = getUnixTime(date, dateFormat); setSelectedTimestamp(selectedTime); const unixTimestamp = getUnixTimestampFromSelectedTimestamp(selectedTime); setUnixTimestamp(unixTimestamp); setExposedDateVariables(unixTimestamp, selectedTime); fireEvent('onSelect'); };

此外,V2 配置中还注册了onFocus与onBlur两个事件(datepickerV2.js),可用于聚焦/失焦时的联动逻辑。

组件特定动作(CSA)

官方文档中注明:

There are currently no CSA (Component-Specific Actions) implemented to regulate or control the component.

该表述针对的是文档对应的旧版组件。需要注意的是,当前仓库的 V2 配置已内置了一组完整的组件动作(datepickerV2.js),这些函数会作为方法暴露到组件对象上,可在 Action 或 JS 中直接调用:

动作参数用途
setValue(value, format)value, format按指定格式写入值
clearValue()无清空当前值
setDate(date, format)date, format仅更新日期部分(保留原有时间)
setValueInTimestamp(value)value以 Unix 时间戳写入
setDisabledDates(value)/clearDisabledDates()value动态设置/清空禁用日期
setMinDate(value)/setMaxDate(value)value动态设置可选日期上下界
setVisibility(value)/setLoading(value)/setDisable(value)value控制可见、加载、禁用态
setFocus()/setBlur()无聚焦/移出焦点

以 datePickerHappyPath.cy.js 端到端测试为例,它逐项断言了上述 13 个函数确实作为Function类型暴露在组件实例上,可视为这些 CSA 可用的直接证据。典型用法如在某按钮的 onClick 中:

// 将日期设为查询结果中的截止日期 {{components.datepicker1.setValue(components.query1.response.due_date, 'DD/MM/YYYY')}} // 或按时间戳写入 {{components.datepicker1.setValueInTimestamp(Date.now())}}

V2 中setDate的实现值得注意:它只替换年/月/日,保留原时间戳中的时分秒(DatePickerV2.jsx),适合“只改日期不改时间”的场景。

暴露变量(Exposed Variables)

文档声明的基础暴露变量:

变量说明访问方式
value用户在组件中输入的值。动态访问,如{{components.datepicker1.value}}。

Legacy 实现中,value会被格式化为format(或format + LT)对应的字符串写入暴露变量(Datepicker.jsx),同时还会额外暴露一个isValid布尔值,表示自定义校验是否通过。

V2 组件则暴露一组更丰富的变量(DatePickerV2.jsx):

const exposedVariables = { value: value, // ISO 字符串(含时区偏移,如 2022-01-01T00:00:00.000+08:00) selectedDate: selectedDate, // 按 dateFormat 格式化的字符串 unixTimestamp: unixTimestamp, // Unix 毫秒时间戳 displayValue: displayValue, // 展示值 dateFormat: dateFormat, isValid: isValid, };

其中value通过 utils.js 的convertToIsoWithTimezoneOffset生成:

export const convertToIsoWithTimezoneOffset = (timestamp, timezone) => { const val = moment.tz(timestamp, timezone).format('YYYY-MM-DDTHH:mm:ss.SSSZ'); return val === 'Invalid date' ? null : val; };

这一设计使 V2 的value天然适合直接传给 API 或数据库的日期字段。端到端测试 datePickerHappyPath.cy.js 也固定校验了selectedDate、displayValue(默认'01/01/2022')与dateFormat(默认'DD/MM/YYYY')等变量的确定性取值。

校验(Validation)

自定义校验

在组件的校验配置中使用三元运算符即可为日期输入添加自定义规则。文档示例——只允许选择今天之后的日期:

{{moment(components.datepicker1.value, 'DD/MM/YYYY').isAfter(moment()) ? true : 'Date should be after today'}}

约定为:表达式返回true表示合法;返回非空字符串时,该字符串作为错误提示展示在组件下方。

V2 版本将校验能力做成了结构化配置(datepickerV2.js):minDate/maxDate(dynamicType: 'date',占位符为DD/MM/YYYY)、disabledDates(dynamicType: 'arrayDate')、customRule(自定义校验表达式)与mandatory(必填开关)。统一校验逻辑集中在 utils.js 的isDateValid中,按优先级依次检查:

if (!isMandatoryValid(isMandatory, selectedDate)) return { isValid: false, validationError: 'Input is mandatory' }; if (!isMinDateValid(minDate, selectedDate, dateFormat) && moment(minDate, dateFormat).isValid()) return { isValid: false, validationError: `Selected date is less than minimum date (${moment(minDate, dateFormat).format(dateFormat)})` }; if (!isMaxDateValid(maxDate, selectedDate, dateFormat) && moment(maxDate, dateFormat).isValid()) return { isValid: false, validationError: `Selected date is greater than maximum date (${moment(maxDate, dateFormat).format(dateFormat)})` }; // ... minTime / maxTime / customRule ... if (excludedDates && excludedDates.length) { const isExcluded = excludedDates.find((date) => moment(date, dateFormat).isSame(selectedDate, 'day')); if (isExcluded) return { isValid: false, validationError: 'Selected date is excluded' }; }

可以看到:必填检查最先执行;min/max 越界会给出带边界值的明确错误文案;customRule若返回非空字符串则直接作为validationError透出——这与文档中三元运算符的写法完全对应。校验结果变化时,组件会同步刷新暴露变量isValid(DatePickerV2.jsx),因此也可以在表单提交前用{{components.datepicker1.isValid}}做二次判断。

通用配置与设备显示

Tooltip

在General(V2 中为 Additional actions 分区)的 Tooltip 字段填入字符串后,鼠标悬停组件即会显示该提示文本。V2 还额外提供格式开关:可选Plain text、Markdown或HTML三种渲染方式(datepickerV2.js),默认plainText。

Devices(设备显示控制)

属性说明取值方式
Show on desktop组件在桌面视图中可见。开关按钮,或点击fx输入逻辑表达式动态控制。
Show on mobile组件在移动视图中可见。开关按钮,或点击fx输入逻辑表达式动态控制。

两份配置的默认值均为桌面显示、移动隐藏:showOnDesktop: '{{true}}'、showOnMobile: '{{false}}'(datepicker.js、datepickerV2.js)。

样式(Styles)

文档声明的样式参数:

样式说明默认值
Visibility控制组件可见性。设为{{false}}后应用部署时组件不显示,仅接受{{true}}/{{false}}。{{true}}
Disable仅接受布尔值。设为{{true}}时组件被锁定、不可操作。{{false}}
Border radius修改日期选择器边框圆角,仅接受1到100的数值。0(Legacy 配置实际默认4)

:::info 任何带有fx按钮的属性都可以以编程方式配置。 :::

在 Legacy 实现中,visibility直接映射为内联样式(Datepicker.jsx):

style={{ height, display: visibility ? '' : 'none', background: 'none', }} aria-hidden={!visibility}

即隐藏组件用display: none并从无障碍树中移除(aria-hidden);disabledState则直接传给react-datepicker的disabled属性锁定交互。borderRadius通过customInput注入到输入框内联样式中(borderRadius: '${borderRadius}px')。

V2 的样式面板进一步扩展为Label / Field / Container三个分组:Label 组包含labelColor、labelFontSize(默认 12)、alignment(side/top);Field 组包含背景色、边框色、强调色(accentColor)、文字色、错误提示色、图标、fieldBorderRadius(默认{{6}})与boxShadow;Container 组提供padding(default/none)选项。默认值均以 CSS 变量(如var(--cc-primary-text))为锚点,便于与全局主题保持一致。

小结

ToolJet 的 Date Picker 覆盖了日期输入场景的核心需求:format+defaultValue联动解析保证默认值有效,disabledDates支持从查询结果动态禁用日期,On select 事件驱动交互流程,三元表达式自定义校验覆盖复杂业务规则,V2 版本再以 Unix 时间戳、ISO 值等暴露变量和十余个 CSA 函数补齐了程序化控制能力。相关实现与测试文件:

  • Legacy 组件配置
  • V2 组件配置
  • Legacy 渲染实现
  • V2 渲染实现
  • 日期解析与校验工具
  • 端到端回归测试
  • 官方组件文档

如需连续日期区间选择,可参考同目录下的 Date Range Picker 文档。

【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询