关于 syncfusion-react-calendars
syncfusion-react-calendars 是介绍 Syncfusion React 日历组件的技能,面向在 React 应用中实现日期选择界面的开发者。内容涵盖 Calendar 和 DatePicker 的配置、事件、样式、本地化及无障碍使用。
主要功能
- 01单日期与多日期选择
- 02月、年和十年视图导航
- 03DatePicker 格式与范围验证
- 04自定义日期单元格和样式
- 05本地化、RTL 与键盘访问
适用场景
- 01在 React 表单中添加日期选择
- 02限制可选日期并校验输入
- 03按区域设置日期格式与周起始日
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ syncfusion/ react-ui-components-skills --skill syncfusion-react-calendars安装后在 Claude Code 中输入/syncfusion-react-calendars确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/calendar-accessibility-globalization.mdcalendar-api-reference.mdcalendar-calendar-views.mdcalendar-date-selection.mdcalendar-events-methods.mdcalendar-getting-started-react.mdcalendar-styling-customization.mddatepicker-accessibility-and-keyboard.mddatepicker-customization-and-styling.mddatepicker-date-formats-and-input.mddatepicker-date-masking-and-strict-mode.mddatepicker-date-range-and-validation.mddatepicker-date-views-and-navigation.mddatepicker-getting-started.mddatepicker-globalization-and-localization.mddaterangepicker-advanced-patterns.mddaterangepicker-api-reference.mddaterangepicker-customization-and-styling.mddaterangepicker-date-range-formatting.mddaterangepicker-date-range-selection.mddaterangepicker-events-and-methods.mddaterangepicker-getting-started.mddatetimepicker-accessibility.mddatetimepicker-advanced-features.mddatetimepicker-api-reference.mddatetimepicker-date-time-selection.mddatetimepicker-events-and-methods.mddatetimepicker-getting-started.mddatetimepicker-styling-and-customization.mddatetimepicker-time-configuration.md详细介绍
实现 Syncfusion React 日历
日历
Syncfusion React CalendarComponent 是一款高度可自定义的日历 UI 控件,允许用户选择一个或多个日期。它支持多种视图(月、年、十年)、导航、周数、禁用日期、自定义日期单元格渲染、本地化、RTL 支持和完整的无障碍功能(符合 WCAG 2.2 标准)。
快速开始(React)
安装
npm install @syncfusion/ej2-react-calendars @syncfusion/ej2-base
基本示例(App.jsx)
import React, { useState } from 'react';
import { CalendarComponent } from '@syncfusion/ej2-react-calendars';
import '@syncfusion/ej2-base/styles/material3.css';
import '@syncfusion/ej2-calendars/styles/material3.css';
export default function App() {
const [value, setValue] = useState(new Date());
const onChange = (args) => setValue(args.value || args);
return (
<div style={{ padding: 20 }}>
<h3>Select a date</h3>
<CalendarComponent value={value} change={onChange} />
<p>Selected: {value.toDateString()}</p>
</div>
);
}
注意:
- 使用
change事件将选定日期同步到 React 状态。 - 导入一次主题 CSS(全局或组件级别),即可为控件设置样式。
指引与模式
- 受控组件: 将 React 状态作为真实数据源,并通过
change事件更新value。 - 多选: 使用
isMultiSelection={true}和values属性,以及addDate()/removeDate()方法。 - 以编程方式导航: 使用
ref调用navigateTo(view, date)——两个参数均为必填项(参见 references/getting-started-react.md)。 - 日期范围: 若要选择日期范围,请使用 DateRangePicker(独立组件)。Calendar 本身没有内置的范围高亮模式。
- 无障碍功能: 使用带有
role="region"的包装元素,并单独设置aria-live区域用于播报;这些并非 Calendar 的直接属性。 - 周数: 使用
weekNumber={true}启用(正确的属性名称)。
参考资料
根据当前任务查阅相应参考资料:
入门指南
📄 阅读: references/getting-started-react.md
- 安装和 npm 设置
- React 组件示例
- CSS/主题导入
- 使用 refs 和方法
日期选择
📄 阅读: references/date-selection.md
- 选择单个日期
- 选择多个日期和日期范围
- 最小/最大值限制
- 禁用特定日期
日历视图
📄 阅读: references/calendar-views.md
- 月、年、十年视图
- 在视图之间导航
- 初始视图和深度控制
- 以编程方式导航
样式与自定义
📄 阅读: references/styling-customization.md
- 主题选择与切换
- CSS 类自定义
- 自定义日期单元格渲染
- RTL 和响应式设计
事件与方法
📄 阅读: references/events-methods.md
- 事件处理程序(change、created、renderDayCell)
- 使用 refs 和命令式方法
- 高级 renderDayCell 钩子
- 事件跟踪模式
无障碍功能与全球化
📄 阅读: references/accessibility-globalization.md
- 符合 WCAG 2.1 标准
- 键盘导航
- ARIA 属性
- 区域设置支持和 RTL
- 无障碍功能测试
API 参考(快速查阅)
📄 阅读: references/api-reference.md
- 一览查看属性、事件和方法
- 常用枚举和类型
- 上游文档链接
故障排除与提示
- 样式未生效: 确认 CSS 导入指向
node_modules/@syncfusion/ej2-calendars/styles/,且在组件样式之前加载。 - React 状态不匹配: 使用
value属性和change事件保持 React 状态同步——不要依赖框架特定的绑定。 - 无法选择多个日期: 确保设置了
isMultiSelection={true},并使用values(而非value)作为初始数组。 navigateTo无效: 该方法需要两个参数——navigateTo(view: CalendarView, date: Date)。- “Cannot find module”: 运行
npm install @syncfusion/ej2-react-calendars @syncfusion/ej2-base并检查package.json。 - 未显示周数: 使用
weekNumber={true}(而非showWeekNumber)。
DatePicker
Syncfusion React DatePickerComponent 提供直观的输入控件,并带有日历弹出窗口,可用于选择单个日期。它支持灵活的格式设置、掩码输入、最小值/最大值日期验证、严格模式、多种输入格式、自定义日期渲染、本地化,并可作为受控 React 组件无缝集成。
组件概览
DatePicker 是 Syncfusion React 日期选择组件,提供丰富的功能:
- 日历弹出窗口 - 通过导航直观地选择日期
- 灵活的格式设置 - 支持带模式的显示格式和输入格式
- 掩码输入 - 使用
enableMask和maskPlaceholder逐段输入日期 - 范围验证 - 设置最小值/最大值日期,并通过
strictMode自动更正 - 多种视图 - 通过
start和depth属性切换月、年和十年视图 - 自定义日期单元格 - 禁用周末,并通过
renderDayCell事件突出显示特殊日期 - 完整的全球化支持 - 支持 150 多种区域性设置、RTL(
enableRtl)、区域特定格式以及firstDayOfWeek - 符合 WCAG 2.2 - 完整的无障碍支持,包括键盘导航和 ARIA 属性
- 适用于表单 - 支持受控组件、React hooks 和表单验证集成
- 程序化控制 -
show()、hide()、focusIn()、focusOut()、navigateTo()、currentView()
完整 API 摘要
关键属性
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
value | Date | null | 所选日期 |
min | Date | 1900-01-01 | 可选日期的最小值 |
max | Date | 2099-12-31 | 可选日期的最大值 |
format | string | FormatObject | null | 显示格式(例如,"dd/MM/yyyy") |
inputFormats | string[] | FormatObject[] | null | 可接受的输入格式数组 |
placeholder | string | null | 输入框的占位文本 |
enabled | boolean | true | 启用或禁用组件 |
readonly | boolean | false | 只读状态 |
allowEdit | boolean | true | 允许编辑输入文本框 |
strictMode | boolean | false | 自动更正超出范围的日期 |
showClearButton | boolean | true | 显示/隐藏清除按钮 |
showTodayButton | boolean | true | 显示/隐藏“今天”按钮 |
start | CalendarView | Month | 初始视图:"Month"、"Year"、"Decade" |
depth | CalendarView | Month | 最深导航级别 |
enableMask | boolean | false | 启用日期掩码输入 |
maskPlaceholder | MaskPlaceholderModel | {...} | 掩码输入的分段占位符 |
enableRtl | boolean | false | 从右到左渲染 |
locale | string | '' | 区域性/区域设置代码 |
firstDayOfWeek | number | 0 | 每周的第一天(0=星期日) |
weekNumber | boolean | false | 显示周数 |
weekRule | WeekRule | FirstDay | 一年中第一周的规则 |
calendarMode | CalendarType | Gregorian | 日历类型(公历或伊斯兰历) |
dayHeaderFormat | DayHeaderFormats | Short | 标题中的星期名称格式 |
floatLabelType | FloatLabelType | Never | 浮动标签行为 |
fullScreenMode | boolean | false | 在移动设备上以全屏方式显示弹出窗口 |
openOnFocus | boolean | false | 输入框获得焦点时打开弹出窗口 |
serverTimezoneOffset | number | null | 服务器时区偏移量 |
cssClass | string | null | 自定义 CSS 类 |
htmlAttributes | { [key: string]: string } | {} | 其他 HTML 属性 |
keyConfigs | { [key: string]: string } | null | 自定义按键操作映射 |
width | number | string | null | 组件宽度 |
zIndex | number | 1000 | 弹出窗口的 z-index |
enablePersistence | boolean | false | 在重新加载之间持久保存状态 |
方法
| 方法 | 返回值 | 描述 |
|---|---|---|
show() | void | 打开日历弹出窗口 |
hide() | void | 关闭日历弹出窗口 |
focusIn() | void | 将焦点设置到组件 |
focusOut() | void | 移除组件焦点 |
navigateTo(view, date) | void | 导航到特定视图和日期 |
currentView() | string | 返回当前日历视图名称 |
getPersistData() | string | 获取持久化状态数据 |
removeDate(dates) | void | 从值中移除日期 |
destroy() | void | 销毁组件 |
事件
| 事件 | 参数类型 | 描述 |
|---|---|---|
change | ChangedEventArgs | 所选日期更改时触发 |
focus | FocusEventArgs | 输入框获得焦点时触发 |
blur | BlurEventArgs | 输入框失去焦点时触发 |
open | PreventableEventArgs | PopupObjectArgs | 弹出窗口打开时触发 |
close | PreventableEventArgs | PopupObjectArgs | 弹出窗口关闭时触发 |
cleared | ClearedEventArgs | 值清除时触发 |
created | Object | 组件创建时触发 |
destroyed | Object | 组件销毁时触发 |
navigated | NavigatedEventArgs | 日历视图导航时触发 |
renderDayCell | RenderDayCellEventArgs | 每个日期单元格渲染时触发 |
文档与导航指南
用户需要 DatePicker 帮助时,请引导其参阅相应文档:
入门
📄 阅读: references/getting-started.md
- 通过 npm 安装(@syncfusion/ej2-react-calendars)
- CSS 主题导入(material3、bootstrap、fluent、tailwind)
- 组件导入和设置
- 使用 DatePickerComponent 的基础 JSX 实现
- 函数组件与类组件示例
- 运行你的第一个应用程序
日期格式与输入
📄 阅读: references/date-formats-and-input.md
- 显示格式属性和格式模式(yyyy-MM-dd、dd/MM/yyyy 等)
- 自定义格式说明符(# 和 0 模式)
- 灵活日期输入的输入格式(接受多种格式)
- 实际场景中的格式示例
- 自动解析并转换用户输入
- 基于区域设置的默认格式
日期范围与验证
📄 阅读: references/date-range-and-validation.md
- 用于限制范围的最小和最大日期属性
- 范围验证和错误状态
- 使用 strictMode 自动更正超出范围的日期
- 超出范围时的行为和错误处理
- 禁用有效范围以外的日期
- 边界情况和注意事项
日期视图与导航
📄 阅读: references/date-views-and-navigation.md
- Start 属性(月、年、十年初始视图)
- 用于限制视图级别的 Depth 属性
- 日历导航和用户交互
- 月份和年份选择快捷方式
- 在不同视图之间导航
- 默认行为和最佳实践
自定义与样式
📄 阅读: references/customization-and-styling.md
- 用于设置样式的 CSS 类(e-datepicker、e-calendar、e-day 等)
- 用于自定义日期的 renderDayCell 事件
- 禁用特定日期和周末
- 占位符、禁用和只读状态
- 自定义 CSS 和主题
- 日期单元格的外观和行为
全球化与本地化
📄 阅读: references/globalization-and-localization.md
- 文化和区域设置配置(德语、法语、阿拉伯语等)
- 加载 CLDR 数据以实现国际化
- 按文化设置日期格式(不同国家使用不同格式)
- 区域文本自定义(“今天”按钮、占位符)
- 支持阿拉伯语、希伯来语、乌尔都语的从右到左(RTL)布局
- 按文化设置每周起始日
- 数字格式设置和日历调整
无障碍功能与键盘导航
📄 阅读: references/accessibility-and-keyboard.md
- 符合 WCAG 2.2 和无障碍标准
- 键盘导航快捷键(Alt+Down、方向键、Esc)
- ARIA 属性(aria-expanded、aria-disabled、aria-activedescendant)
- 屏幕阅读器支持和播报
- 焦点管理和可见的焦点指示器
- 色彩对比度和视觉无障碍
- 支持移动设备
日期遮罩与高级验证
📄 阅读: references/date-masking-and-strict-mode.md
enableMask属性,用于按结构化的分段逐步输入日期maskPlaceholder,用于设置自定义的分段占位文本- 用于输入提示的日期遮罩模式
strictMode属性的行为和强制规则- 日期解析规则和验证逻辑
- 输入验证和格式强制
- 边缘情况(闰年、月份边界等)
- 常见验证问题的故障排除
- 日期输入最佳实践
快速入门示例
下面是一个可供上手使用的最简示例:
import React, { useState } from 'react';
import { DatePickerComponent } from '@syncfusion/ej2-react-calendars';
import '@syncfusion/ej2-base/styles/material3.css';
import '@syncfusion/ej2-buttons/styles/material3.css';
import '@syncfusion/ej2-inputs/styles/material3.css';
import '@syncfusion/ej2-popups/styles/material3.css';
import '@syncfusion/ej2-react-calendars/styles/material3.css';
export default function App() {
const [selectedDate, setSelectedDate] = useState(new Date());
return (
<div style={{ padding: '20px' }}>
<h3>Select a Date</h3>
<DatePickerComponent
value={selectedDate}
change={(e) => setSelectedDate(e.value)}
placeholder="Enter date"
/>
<p>Selected: {selectedDate?.toDateString()}</p>
</div>
);
}
要点:
- 从
@syncfusion/ej2-react-calendars导入DatePickerComponent - 导入所有必需的 CSS 主题(基础、按钮、输入框、弹出窗口、日历)
- 使用
value属性设置当前日期(可以是 null 或 Date 对象) - 使用
change事件(而非onChange)更新 React 状态——这是 Syncfusion 的事件名称 - 点击或按 Alt+Down 方向键时,DatePicker 会打开日历弹出窗口
常见模式
1. 日期范围选择器(最小/最大日期)
<DatePickerComponent
value={new Date()}
min={new Date(2026, 0, 1)}
max={new Date(2026, 11, 31)}
placeholder="Select a date in 2026"
/>
2. 自定义日期格式
<DatePickerComponent
value={new Date()}
format="dd/MM/yyyy"
placeholder="DD/MM/YYYY"
/>
3. 多种可接受的输入格式
<DatePickerComponent
value={new Date()}
format="yyyy-MM-dd"
inputFormats={['dd/MM/yyyy', 'yyyy-MM-dd', 'yyyyMMdd']}
placeholder="Enter date (dd/MM/yyyy or yyyy-MM-dd)"
/>
4. 用于选择出生日期的年份/十年视图
<DatePickerComponent
value={new Date()}
start="Decade"
depth="Year"
placeholder="Select year"
/>
5. 禁用周末
<DatePickerComponent
value={new Date()}
renderDayCell={(args) => {
if ((args.date.getDay()) === 0 || (args.date.getDay()) === 6) {
args.isDisabled = true;
}
}}
placeholder="Weekdays only"
/>
6. React 表单中的受控组件
const [date, setDate] = useState(null);
<DatePickerComponent
value={date}
change={(e) => setDate(e.value)}
format="yyyy-MM-dd"
strictMode={true}
placeholder="Enter date"
/>
7. 支持 RTL 的德语文化设置
<DatePickerComponent
locale="de"
enableRtl={false}
firstDayOfWeek={1}
value={new Date()}
placeholder="Datum eingeben"
/>
8. 带遮罩的日期输入
<DatePickerComponent
enableMask={true}
format="MM/dd/yyyy"
maskPlaceholder={{ day: 'DD', month: 'MM', year: 'YYYY' }}
placeholder="Select a date"
/>
9. 以编程方式控制
import { useRef } from 'react';
const datePickerRef = useRef(null);
// Open calendar
datePickerRef.current.show();
// Close calendar
datePickerRef.current.hide();
// Focus
datePickerRef.current.focusIn();
// Get current view
const view = datePickerRef.current.currentView(); // "Month" | "Year" | "Decade"
// Navigate to specific view
datePickerRef.current.navigateTo('Year', new Date(2026, 0, 1));
<DatePickerComponent ref={datePickerRef} value={new Date()} />
10. 处理所有按键事件
<DatePickerComponent
value={new Date()}
change={(e) => console.log('Changed:', e.value)}
focus={(e) => console.log('Focused')}
blur={(e) => console.log('Blurred')}
open={(e) => console.log('Opened')}
close={(e) => console.log('Closed')}
cleared={(e) => console.log('Cleared')}
navigated={(e) => console.log('Navigated to view:', e.view)}
renderDayCell={(args) => {
// Disable weekends
if (args.date.getDay() === 0 || args.date.getDay() === 6) {
args.isDisabled = true;
}
}}
/>
DateRangePicker
Syncfusion React DateRangePickerComponent 支持用户选择开始和结束日期,并内置预设、验证、自定义格式、分隔符配置、全屏移动模式以及高级范围约束(minDays、maxDays、min、max)。
文档导航指南
开始使用
📄 阅读: references/getting-started.md
- 通过 npm 安装(@syncfusion/ej2-react-calendars)
- CSS 导入和主题配置
- 基本的 DateRangePicker 实现
- 类组件与函数组件的设置
- 组件初始化和结构
- 运行开发服务器
- 常见故障排除
日期范围选择
📄 阅读: references/date-range-selection.md
- 开始和结束日期属性
- 日期范围验证模式
- 最小和最大日期约束
- 禁用日期配置
- 日期范围预设(过去 7 天、过去 30 天等)
- 值绑定和双向更新
- 只读和禁用状态
- 占位符和标签
日期范围格式
📄 阅读: references/date-range-formatting.md
- 日期格式字符串选项(MM/dd/yyyy、dd-MMM-yyyy 等)
- 显示格式与输入格式
- 基于区域设置的日期格式
- 起止日期之间的自定义分隔符
- 浮动标签类型(Never、Always、Auto)
- 自定义占位文本
- 用于 DOM 属性的 htmlAttributes
事件和方法
📄 阅读: references/events-and-methods.md
- 事件处理程序(change、open、close、blur、focus、select)
- 事件参数结构
- 方法(show、hide、focusIn、focusOut、reset、destroy)
- 使用 useRef 进行命令式控制
- 生命周期事件(created、destroyed)
- 事件模式和最佳实践
- 清除值并重置状态
- DateRangeSelectingEvent 和 ChangedEventArgs
自定义和样式
📄 阅读: references/customization-and-styling.md
- 使用 cssClass 自定义 CSS 类
- 主题选项(Material、Bootstrap、Fluent、Tailwind、Fabric)
- 面向移动设备的全屏模式
- RTL(从右向左)语言支持
- 自定义预设范围
- Z-index 管理
- 宽度和高度配置
- 无障碍功能和 ARIA 属性
API 参考
📄 阅读: references/api-reference.md
- 完整的属性列表(35+ 个属性)
- 所有方法及其签名(8 个方法)
- 所有事件及其事件参数(12 个事件)
- 类型定义和接口
- 默认值和限制条件
- 各属性和方法的用例
高级模式
📄 阅读: references/advanced-patterns.md
- 带日期范围验证的表单提交
- 键盘快捷键和按键导航
- 服务器时区偏移处理
- 持久化和 localStorage
- 多组件集成(起止日期绑定)
- 使用延迟加载优化性能
- 错误处理和验证模式
- 复杂日期范围场景(财年、季度)
快速入门
import { DateRangePickerComponent } from '@syncfusion/ej2-react-calendars';
import * as React from 'react';
import '@syncfusion/ej2-base/styles/material3.css';
import '@syncfusion/ej2-buttons/styles/material3.css';
import '@syncfusion/ej2-lists/styles/material3.css';
import '@syncfusion/ej2-inputs/styles/material3.css';
import '@syncfusion/ej2-popups/styles/material3.css';
import '@syncfusion/ej2-calendars/styles/material3.css';
function App() {
const [selectedRange, setSelectedRange] = React.useState<[Date, Date] | null>(null);
const handleDateRangeChange = (e: any) => {
setSelectedRange([e.startDate, e.endDate]);
};
return (
<div style={{ padding: '20px' }}>
<h2>Select Date Range</h2>
<DateRangePickerComponent
id="daterangepicker"
placeholder="Select a range"
change={handleDateRangeChange}
/>
{selectedRange && (
<p>
Selected: {selectedRange[0]?.toLocaleDateString()} - {selectedRange[1]?.toLocaleDateString()}
</p>
)}
</div>
);
}
export default App;
常见模式
模式 1:带预设选项的日期范围
import { DateRangePickerComponent } from '@syncfusion/ej2-react-calendars';
import * as React from 'react';
function ReportingDashboard() {
const [dateRange, setDateRange] = React.useState<[Date, Date] | null>(null);
const getDateRangePresets = () => {
const today = new Date();
const yesterday = new Date(today);
yesterday.setDate(today.getDate() - 1);
const last7Days = new Date(today);
last7Days.setDate(today.getDate() - 7);
const last30Days = new Date(today);
last30Days.setDate(today.getDate() - 30);
const thisMonth = new Date(today.getFullYear(), today.getMonth(), 1);
const lastMonth = new Date(today.getFullYear(), today.getMonth(), 0);
return [
{ text: 'Today', value: [today, today] },
{ text: 'Yesterday', value: [yesterday, yesterday] },
{ text: 'Last 7 Days', value: [last7Days, today] },
{ text: 'Last 30 Days', value: [last30Days, today] },
{ text: 'This Month', value: [thisMonth, today] },
{ text: 'Last Month', value: [new Date(today.getFullYear(), today.getMonth() - 1, 1), lastMonth] },
];
};
const handlePresetClick = (start: Date, end: Date) => {
setDateRange([start, end]);
};
return (
<div style={{ padding: '20px' }}>
<h3>Analytics Report</h3>
<DateRangePickerComponent
id="daterangepicker"
placeholder="Select report date range"
startDate={dateRange?.[0]}
endDate={dateRange?.[1]}
change={(e: any) => setDateRange([e.startDate, e.endDate])}
/>
<div style={{ marginTop: '15px' }}>
{getDateRangePresets().map((preset) => (
<button
key={preset.text}
onClick={() => handlePresetClick(preset.value[0], preset.value[1])}
style={{ marginRight: '10px', padding: '5px 10px' }}
>
{preset.text}
</button>
))}
</div>
</div>
);
}
export default ReportingDashboard;
模式 2:带验证的日期范围
import { DateRangePickerComponent } from '@syncfusion/ej2-react-calendars';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import * as React from 'react';
function BookingForm() {
const [dateRange, setDateRange] = React.useState<[Date, Date] | null>(null);
const [validationError, setValidationError] = React.useState<string>('');
const minDate = new Date();
const maxDate = new Date();
maxDate.setDate(maxDate.getDate() + 90); // 90 days from now
const handleDateRangeChange = (e: any) => {
setValidationError('');
if (!e.startDate || !e.endDate) {
return;
}
const start = new Date(e.startDate);
const end = new Date(e.endDate);
// Validation checks
if (start > end) {
setValidationError('Start date must be before end date');
return;
}
const daysDifference = (end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24);
if (daysDifference > 30) {
setValidationError('Date range cannot exceed 30 days');
return;
}
setDateRange([start, end]);
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (dateRange && !validationError) {
console.log('Booking dates:', {
checkIn: dateRange[0].toLocaleDateString(),
checkOut: dateRange[1].toLocaleDateString(),
});
}
};
return (
<form onSubmit={handleSubmit} style={{ padding: '20px', maxWidth: '500px' }}>
<h3>Book Your Stay</h3>
<label style={{ display: 'block', marginBottom: '8px' }}>
Select Check-in and Check-out Dates (Max 30 days)
</label>
<DateRangePickerComponent
id="daterangepicker"
placeholder="Select check-in and check-out"
min={minDate}
max={maxDate}
startDate={dateRange?.[0]}
endDate={dateRange?.[1]}
change={handleDateRangeChange}
style={{ width: '100%', marginBottom: '8px' }}
/>
{validationError && (
<div style={{ color: 'red', marginBottom: '10px', fontSize: '14px' }}>
⚠️ {validationError}
</div>
)}
<ButtonComponent
type="submit"
isPrimary={true}
disabled={!dateRange || !!validationError}
>
Book Now
</ButtonComponent>
</form>
);
}
export default BookingForm;
模式 4:事件处理和状态管理
import { DateRangePickerComponent } from '@syncfusion/ej2-react-calendars';
import * as React from 'react';
function EventTrackingExample() {
const [dateRange, setDateRange] = React.useState<[Date, Date] | null>(null);
const [eventLog, setEventLog] = React.useState<string[]>([]);
const handleSelect = (e: any) => {
setEventLog(prev => [
...prev,
`Selected: ${e.startDate?.toLocaleDateString()} to ${e.endDate?.toLocaleDateString()}`
]);
};
const handleChange = (e: any) => {
setDateRange([e.startDate, e.endDate]);
setEventLog(prev => [...prev, `Changed: ${new Date().toLocaleTimeString()}`]);
};
const handleOpen = (e: any) => {
setEventLog(prev => [...prev, `Popup opened at ${new Date().toLocaleTimeString()}`]);
};
const handleClose = (e: any) => {
setEventLog(prev => [...prev, `Popup closed at ${new Date().toLocaleTimeString()}`]);
};
const clearLog = () => {
setEventLog([]);
};
return (
<div style={{ padding: '20px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }}>
<div>
<h3>DateRangePicker</h3>
<DateRangePickerComponent
id="daterangepicker"
placeholder="Select date range"
select={handleSelect}
change={handleChange}
open={handleOpen}
close={handleClose}
/>
</div>
<div style={{ padding: '10px', border: '1px solid #ccc', borderRadius: '4px' }}>
<h3>Event Log</h3>
<button
onClick={clearLog}
style={{
padding: '5px 10px',
marginBottom: '10px',
backgroundColor: '#f0f0f0',
border: '1px solid #ccc',
cursor: 'pointer'
}}
>
Clear Log
</button>
<ul style={{ maxHeight: '300px', overflowY: 'auto', margin: 0, paddingLeft: '20px' }}>
{eventLog.map((event, idx) => (
<li key={idx} style={{ marginBottom: '5px', fontSize: '12px' }}>
{event}
</li>
))}
</ul>
</div>
</div>
);
}
export default EventTrackingExample;
模式 5:自定义日期范围格式
import { DateRangePickerComponent } from '@syncfusion/ej2-react-calendars';
import * as React from 'react';
function DateFormatDemo() {
const [formatType, setFormatType] = React.useState<'short' | 'long' | 'custom'>('short');
const [dateRange, setDateRange] = React.useState<[Date, Date] | null>(null);
const getFormat = () => {
switch (formatType) {
case 'short':
return 'M/d/yyyy';
case 'long':
return 'MMMM d, yyyy';
case 'custom':
return 'dd-MMM-yy';
default:
return 'M/d/yyyy';
}
};
return (
<div style={{ padding: '20px' }}>
<h3>Date Range Format Options</h3>
<div style={{ marginBottom: '15px' }}>
<label style={{ marginRight: '10px' }}>Format Type:</label>
{(['short', 'long', 'custom'] as const).map((format) => (
<label key={format} style={{ marginRight: '15px' }}>
<input
type="radio"
name="format"
value={format}
checked={formatType === format}
onChange={(e) => setFormatType(e.target.value as any)}
/>
{format.charAt(0).toUpperCase() + format.slice(1)}
</label>
))}
</div>
<div style={{ marginBottom: '10px', padding: '10px', backgroundColor: '#f5f5f5' }}>
<strong>Format String:</strong> {getFormat()}
</div>
<DateRangePickerComponent
id="daterangepicker"
placeholder="Select date range"
format={getFormat()}
startDate={dateRange?.[0]}
endDate={dateRange?.[1]}
change={(e: any) => setDateRange([e.startDate, e.endDate])}
/>
{dateRange && (
<div style={{ marginTop: '15px', padding: '10px', backgroundColor: '#e8f5e9' }}>
<p>
<strong>Formatted Output:</strong> {dateRange[0].toLocaleDateString('en-US')} - {dateRange[1].toLocaleDateString('en-US')}
</p>
</div>
)}
</div>
);
}
export default DateFormatDemo;
主要属性参考
- 属性:
startDate:类型:Date— 默认值:null— 范围的初始开始日期。 - 属性:
endDate:类型:Date— 默认值:null— 范围的初始结束日期。 - 属性:
min:类型:Date— 默认值:new Date(1900, 0, 1)— 可选择的最早日期。 - 属性:
max:类型:Date— 默认值:new Date(2099, 11, 31)— 可选择的最晚日期。 - 属性:
value:类型:Date[] | DateRange— 默认值:null— 获取或设置开始日期和结束日期。 - 属性:
format:类型:string | RangeFormatObject— 默认值:null— 日期显示和输入格式。 - 属性:
placeholder:类型:string— 默认值:null— 输入占位文本。 - 属性:
enabled:类型:boolean— 默认值:true— 启用或禁用组件(使用enabled,而不是disabled)。 - 属性:
readonly:类型:boolean— 默认值:false— 只读状态;禁止编辑。 - 属性:
allowEdit:类型:boolean— 默认值:true— 允许手动编辑输入文本。 - 属性:
cssClass:类型:string— 默认值:''— 为根元素添加自定义 CSS 类。 - 属性:
floatLabelType:类型:FloatLabelType | string— 默认值:Never— 浮动标签行为(Never、Always、Auto)。 - 属性:
separator:类型:string— 默认值:'-'— 输入框中开始日期和结束日期之间的分隔符字符串。 - 属性:
locale:类型:string— 默认值:'en-US'— 用于格式设置和本地化的区域设置。 - 属性:
inputFormats:类型:string[] | RangeFormatObject[]— 默认值:null— 可接受的输入解析格式。 - 属性:
keyConfigs:类型:object— 默认值:null— 自定义键盘快捷键映射。 - 属性:
firstDayOfWeek:类型:number— 默认值:null— 日历中一周的第一天。 - 属性:
dayHeaderFormat:类型:DayHeaderFormats— 默认值:Short— 标题中的星期名称格式。 - 属性:
start:类型:CalendarView— 默认值:Month— 弹出窗口打开时的初始日历视图。 - 属性:
depth:类型:CalendarView— 默认值:Month— 日历的最大导航深度。 - 属性:
weekNumber:类型:boolean— 默认值:false— 在日历行中显示周数。 - 属性:
weekRule:类型:WeekRule— 默认值:FirstDay— 定义一年中第一周的规则。 - 属性:
minDays:类型:number— 默认值:null— 选择范围允许的最小天数。 - 属性:
maxDays:类型:number— 默认值:null— 选择范围允许的最大天数。 - 属性:
strictMode:类型:boolean— 默认值:false— 为 true 时,只能输入有效范围。 - 属性:
showClearButton:类型:boolean— 默认值:true— 切换清除按钮的可见性。 - 属性:
fullScreenMode:类型:boolean— 默认值:false— 在移动设备上使用全屏弹出窗口。 - 属性:
htmlAttributes:类型:{ [key: string]: string }— 默认值:{}— 应用于组件元素的其他 HTML 属性。 - 属性:
serverTimezoneOffset:类型:number— 默认值:null— 处理初始值时使用的服务器时区偏移量(分钟)。 - 属性:
width:类型:number | string— 默认值:''— 组件输入框的宽度。 - 属性:
zIndex:类型:number— 默认值:1000— 弹出元素的 z-index。
后续步骤:
- 阅读 references/getting-started.md,安装并设置你的第一个 DateRangePicker
- 探索 references/date-range-selection.md,了解范围选择模式
- 查看 references/date-range-formatting.md,了解格式选项
- 阅读 references/advanced-patterns.md,了解复杂场景
- 参阅 references/api-reference.md,查看完整的 API 文档
DateTimePicker
Syncfusion React DateTimePickerComponent 将日期和时间选择整合到一个控件中。它提供日历 + 时间列表弹出窗口、可自定义的时间间隔、掩码、严格验证、时区处理、格式自定义以及完整的键盘辅助功能。
文档(请按顺序阅读以下参考资料)
- 📄 阅读:references/getting-started.md — 安装、模块设置、CSS 导入、基本用法
- 📄 阅读:references/api-reference.md — 完整的属性、方法和事件
- 📄 阅读:references/date-time-selection.md — 选择模式和限制条件
- 📄 阅读:references/time-configuration.md — 时间间隔、minTime/maxTime、滚动行为
- 📄 阅读:references/events-and-methods.md — 事件处理程序和方法用法
- 📄 阅读:references/styling-and-customization.md — 主题和 cssClass 用法
- 📄 阅读:references/advanced-features.md — 掩码输入、严格模式、日历模式、时区处理
- 📄 阅读:references/accessibility.md — 键盘和 ARIA 指南
快速入门(React + TypeScript)
- 安装软件包:
npm install @syncfusion/ej2-react-calendars
- 导入样式(在
index.css或组件 CSS 中):
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-calendars/styles/material3.css';
- 最简可运行示例(
App.tsx):
import React, { useState } from 'react';
import { DateTimePickerComponent } from '@syncfusion/ej2-react-calendars';
export default function App() {
const [value, setValue] = useState<Date | null>(new Date());
return (
<div style={{ padding: 20 }}>
<h3>Choose date and time</h3>
<DateTimePickerComponent
value={value}
change={(e) => setValue((e as any).value)}
format="dd/MM/yyyy hh:mm a"
step={15}
placeholder="Select date and time"
/>
<p>Selected: {value ? value.toString() : 'none'}</p>
</div>
);
}
常见模式
- 受控值:绑定
value,并在change时更新。 - 范围限制:日期使用
min和max,时间使用minTime/maxTime。 - 掩码输入:通过
enableMask启用,并提供maskPlaceholder。 - 本地化:设置
locale或使用全局区域设置。 - 键盘优先:通过
keyConfigs提供自定义快捷键。
关键属性摘要(完整列表请参阅 API 参考)
value、min、max、step、format、enableMask、placeholder、cssClass、locale、readonly、enabled。
关键事件
change、open、close、created、destroyed、navigated、blur、focus、renderDayCell。
后续步骤
- 所有参考文件均已创建,并已根据 Syncfusion 官方 API 验证(请参阅
references/api-reference.md)。 - 接下来:运行测试用例指南和验证检查,然后创建自动化示例,或根据请求添加特定平台的说明。
- 请让我运行测试、更新
completion-status.json,或生成可发布的产物。
TimePicker
Syncfusion React TimePickerComponent 是一款轻量且功能丰富的时间选择控件。它支持 12/24 小时格式、时间间隔、最小/最大值限制、掩码输入、本地化、全屏模式,并可轻松集成到 React 表单中。
文档导航指南
入门
📄 阅读: references/getting-started.md
- 通过 npm 安装 (@syncfusion/ej2-react-calendars)
- 在 app.module.ts 中设置 CalendarModule
- CSS 导入和主题配置
- TimePicker 基本实现
- 使用 useRef 注册组件
- 运行开发服务器
- 常见故障排除
时间格式和显示
📄 阅读: references/time-format-and-display.md
- 格式字符串选项(24 小时制、12 小时制)
- 带有 skeleton 属性的 TimeFormatObject
- 基于区域设置的时间格式
- 占位文本自定义
- 浮动标签类型(Never、Always、Auto)
- 用于 DOM 属性的 htmlAttributes
- 使用 enableMask 实现掩码输入
- 掩码占位符配置
时间范围和选择
📄 阅读: references/time-range-and-selection.md
- 最小和最大时间限制
- 时间步长间隔(15、30、60 分钟)
- ScrollTo 默认位置
- 值绑定和双向更新
- 只读和禁用状态
- OpenOnFocus 行为
- 时间弹出列表填充
- 分步时间间隔
事件和方法
📄 阅读: references/events-and-methods.md
- 事件处理程序(change、open、close、blur、focus)
- 事件参数结构
- 方法(show、hide、focusIn、focusOut)
- 使用 useRef 进行命令式控制
- 生命周期事件(created、destroyed)
- 事件模式和最佳实践
- 清除值和重置状态
- 用于自定义格式的 ItemRender
自定义和样式
📄 阅读: references/customization-and-styling.md
- 使用 cssClass 自定义 CSS 类
- 主题选项(Material、Bootstrap、Fluent、Tailwind)
- 面向移动设备的全屏模式
- RTL(从右向左)语言支持
- 严格模式验证
- Z-index 管理
- 宽度和高度配置
- 无障碍功能
- 与 Theme Studio 集成
API 参考
📄 阅读: references/api-reference.md
- 完整的属性列表(26 个属性)
- 所有方法及其签名(5 个方法)
- 所有事件及其事件参数(9 个事件)
- 类型定义和接口
- 默认值和限制
- 每个属性的使用场景
高级模式
📄 阅读: references/advanced-patterns.md
- 带验证的表单提交
- 键盘快捷键和 keyConfigs
- 服务器时区偏移处理
- 持久化和 localStorage
- 多组件集成
- 性能优化
- 错误处理模式
- 复杂验证场景
快速开始
import { TimePickerComponent } from '@syncfusion/ej2-react-calendars';
import * as React from 'react';
import '@syncfusion/ej2-base/styles/material3.css';
import '@syncfusion/ej2-calendars/styles/material3.css';
function App() {
const [selectedTime, setSelectedTime] = React.useState(new Date('1/1/2018 9:00 AM'));
const handleChange = (e: any) => {
setSelectedTime(e.value);
};
return (
<div style={{ padding: '20px' }}>
<h2>Select Time</h2>
<TimePickerComponent
value={selectedTime}
change={handleChange}
placeholder="Select a time"
/>
<p>Selected: {selectedTime ? selectedTime.toLocaleTimeString() : 'None'}</p>
</div>
);
}
export default App;
常见模式
模式 1:带最小值/最大值限制的时间选择器
import { TimePickerComponent } from '@syncfusion/ej2-react-calendars';
import * as React from 'react';
function AppointmentScheduler() {
const [appointmentTime, setAppointmentTime] = React.useState(new Date('1/1/2018 9:00 AM'));
const minTime = new Date('1/1/2018 8:00 AM');
const maxTime = new Date('1/1/2018 5:00 PM');
return (
<div>
<h3>Select Appointment Time (8 AM - 5 PM)</h3>
<TimePickerComponent
value={appointmentTime}
min={minTime}
max={maxTime}
step={30}
change={(e: any) => setAppointmentTime(e.value)}
placeholder="Choose time"
/>
</div>
);
}
export default AppointmentScheduler;
模式 2:带时间选择器的表单提交
import { TimePickerComponent } from '@syncfusion/ej2-react-calendars';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import * as React from 'react';
function ScheduleForm() {
const [formData, setFormData] = React.useState({
startTime: new Date('1/1/2018 9:00 AM'),
endTime: new Date('1/1/2018 5:00 PM'),
});
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
console.log('Schedule data:', {
startTime: formData.startTime?.toLocaleTimeString(),
endTime: formData.endTime?.toLocaleTimeString(),
});
};
return (
<form onSubmit={handleSubmit}>
<h3>Schedule Meeting</h3>
<label>Start Time:</label>
<TimePickerComponent
value={formData.startTime}
change={(e: any) => setFormData(prev => ({ ...prev, startTime: e.value }))}
/>
<label style={{ marginTop: '10px' }}>End Time:</label>
<TimePickerComponent
value={formData.endTime}
min={formData.startTime}
change={(e: any) => setFormData(prev => ({ ...prev, endTime: e.value }))}
/>
<ButtonComponent type="submit" isPrimary={true} style={{ marginTop: '15px' }}>
Schedule
</ButtonComponent>
</form>
);
}
export default ScheduleForm;
模式 3:使用自定义格式的时间选择器
import { TimePickerComponent } from '@syncfusion/ej2-react-calendars';
import * as React from 'react';
function TimeFormatDemo() {
const [time12hr, setTime12hr] = React.useState(new Date('1/1/2018 2:30 PM'));
const [time24hr, setTime24hr] = React.useState(new Date('1/1/2018 14:30'));
return (
<div style={{ padding: '20px' }}>
<div>
<h4>12-Hour Format (hh:mm a)</h4>
<TimePickerComponent
value={time12hr}
format="hh:mm a"
change={(e: any) => setTime12hr(e.value)}
/>
<p>Value: {time12hr?.toLocaleTimeString('en-US', { hour12: true })}</p>
</div>
<div style={{ marginTop: '20px' }}>
<h4>24-Hour Format (HH:mm)</h4>
<TimePickerComponent
value={time24hr}
format="HH:mm"
change={(e: any) => setTime24hr(e.value)}
/>
<p>Value: {time24hr?.toLocaleTimeString('en-US', { hour12: false })}</p>
</div>
</div>
);
}
export default TimeFormatDemo;
模式 4:事件处理和状态管理
import { TimePickerComponent } from '@syncfusion/ej2-react-calendars';
import * as React from 'react';
function EventTrackingExample() {
const [selectedTime, setSelectedTime] = React.useState<Date | null>(null);
const [eventLog, setEventLog] = React.useState<string[]>([]);
const handleChange = (e: any) => {
setSelectedTime(e.value);
setEventLog(prev => [...prev, `Changed: ${e.value?.toLocaleTimeString()}`]);
};
const handleOpen = (e: any) => {
setEventLog(prev => [...prev, 'Popup opened']);
};
const handleClose = (e: any) => {
setEventLog(prev => [...prev, 'Popup closed']);
};
return (
<div style={{ padding: '20px' }}>
<h3>Time Picker with Event Tracking</h3>
<TimePickerComponent
value={selectedTime}
change={handleChange}
open={handleOpen}
close={handleClose}
placeholder="Select time to track events"
/>
<div style={{ marginTop: '20px', padding: '10px', border: '1px solid #ccc' }}>
<h4>Event Log:</h4>
<ul>
{eventLog.map((event, idx) => (
<li key={idx}>{event}</li>
))}
</ul>
</div>
</div>
);
}
export default EventTrackingExample;
模式 5:带掩码的时间输入
import { TimePickerComponent } from '@syncfusion/ej2-react-calendars';
import * as React from 'react';
function MaskedTimePickerExample() {
const [maskedTime, setMaskedTime] = React.useState(new Date('1/1/2018 10:30 AM'));
return (
<div style={{ padding: '20px' }}>
<h3>Masked Time Input</h3>
<TimePickerComponent
value={maskedTime}
enableMask={true}
format="hh:mm a"
maskPlaceholder={{
hour: 'HH',
minute: 'MM',
second: 'SS',
}}
change={(e: any) => setMaskedTime(e.value)}
placeholder="Enter time (HH:MM AM/PM)"
/>
<p>Masked input helps users enter time in correct format</p>
</div>
);
}
export default MaskedTimePickerExample;
关键属性参考
| 属性 | 类型 | 默认值 | 用途 |
|---|---|---|---|
value | Date | null | 当前选中的时间值 |
format | string | 根据区域设置 | 时间显示格式(例如,"HH:mm"、"hh:mm a") |
min | Date | 00:00 | 可选时间的最小值 |
max | Date | 00:00 | 可选时间的最大值 |
step | number | 30 | 列表项之间的时间间隔(分钟) |
enabled | boolean | true | 启用/禁用组件 |
readonly | boolean | false | 只读状态(不可编辑) |
placeholder | string | - | 输入框占位文本 |
openOnFocus | boolean | false | 输入框获得焦点时打开弹出窗口 |
enableMask | boolean | false | 启用掩码输入模式 |
enableRtl | boolean | false | 启用从右到左的布局 |
strictMode | boolean | false | 验证输入并将其限制为有效时间 |
showClearButton | boolean | true | 显示/隐藏清除按钮 |
fullScreenMode | boolean | false | 移动端全屏模式 |
cssClass | string | - | 用于设置样式的自定义 CSS 类 |
floatLabelType | string | Never | 浮动标签位置 |
allowEdit | boolean | true | 允许手动编辑输入 |
locale | string | 'en-US' | 用于时间格式化的区域设置 |
scrollTo | Date | - | 弹出窗口中的默认滚动位置 |
width | string/number | - | 组件宽度 |
zIndex | number | 1000 | 弹出窗口的 Z-index |
serverTimezoneOffset | number | - | 用于处理的服务器时区偏移量 |
htmlAttributes | object | {} | 自定义 HTML 属性 |
后续步骤:
- 阅读 references/getting-started.md,安装并设置你的第一个 TimePicker
- 查看 references/time-format-and-display.md,了解格式选项
- 查看 references/time-range-and-selection.md,了解时间限制
- 查看 references/advanced-patterns.md,了解复杂场景