mcpField
S
syncfusion-react-calendars

syncfusion-react-calendars

github.com/syncfusion开发3549 次安装1 周前更新
代码仓库

关于 syncfusion-react-calendars

syncfusion-react-calendars 是介绍 Syncfusion React 日历组件的技能,面向在 React 应用中实现日期选择界面的开发者。内容涵盖 Calendar 和 DatePicker 的配置、事件、样式、本地化及无障碍使用。

主要功能

  1. 01单日期与多日期选择
  2. 02月、年和十年视图导航
  3. 03DatePicker 格式与范围验证
  4. 04自定义日期单元格和样式
  5. 05本地化、RTL 与键盘访问

适用场景

  1. 01在 React 表单中添加日期选择
  2. 02限制可选日期并校验输入
  3. 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.md
calendar-api-reference.md
calendar-calendar-views.md
calendar-date-selection.md
calendar-events-methods.md
calendar-getting-started-react.md
calendar-styling-customization.md
datepicker-accessibility-and-keyboard.md
datepicker-customization-and-styling.md
datepicker-date-formats-and-input.md
datepicker-date-masking-and-strict-mode.md
datepicker-date-range-and-validation.md
datepicker-date-views-and-navigation.md
datepicker-getting-started.md
datepicker-globalization-and-localization.md
daterangepicker-advanced-patterns.md
daterangepicker-api-reference.md
daterangepicker-customization-and-styling.md
daterangepicker-date-range-formatting.md
daterangepicker-date-range-selection.md
daterangepicker-events-and-methods.md
daterangepicker-getting-started.md
datetimepicker-accessibility.md
datetimepicker-advanced-features.md
datetimepicker-api-reference.md
datetimepicker-date-time-selection.md
datetimepicker-events-and-methods.md
datetimepicker-getting-started.md
datetimepicker-styling-and-customization.md
datetimepicker-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 摘要
关键属性
属性类型默认值描述
valueDatenull所选日期
minDate1900-01-01可选日期的最小值
maxDate2099-12-31可选日期的最大值
formatstring | FormatObjectnull显示格式(例如,"dd/MM/yyyy")
inputFormatsstring[] | FormatObject[]null可接受的输入格式数组
placeholderstringnull输入框的占位文本
enabledbooleantrue启用或禁用组件
readonlybooleanfalse只读状态
allowEditbooleantrue允许编辑输入文本框
strictModebooleanfalse自动更正超出范围的日期
showClearButtonbooleantrue显示/隐藏清除按钮
showTodayButtonbooleantrue显示/隐藏“今天”按钮
startCalendarViewMonth初始视图:"Month"、"Year"、"Decade"
depthCalendarViewMonth最深导航级别
enableMaskbooleanfalse启用日期掩码输入
maskPlaceholderMaskPlaceholderModel{...}掩码输入的分段占位符
enableRtlbooleanfalse从右到左渲染
localestring''区域性/区域设置代码
firstDayOfWeeknumber0每周的第一天(0=星期日)
weekNumberbooleanfalse显示周数
weekRuleWeekRuleFirstDay一年中第一周的规则
calendarModeCalendarTypeGregorian日历类型(公历或伊斯兰历)
dayHeaderFormatDayHeaderFormatsShort标题中的星期名称格式
floatLabelTypeFloatLabelTypeNever浮动标签行为
fullScreenModebooleanfalse在移动设备上以全屏方式显示弹出窗口
openOnFocusbooleanfalse输入框获得焦点时打开弹出窗口
serverTimezoneOffsetnumbernull服务器时区偏移量
cssClassstringnull自定义 CSS 类
htmlAttributes{ [key: string]: string }{}其他 HTML 属性
keyConfigs{ [key: string]: string }null自定义按键操作映射
widthnumber | stringnull组件宽度
zIndexnumber1000弹出窗口的 z-index
enablePersistencebooleanfalse在重新加载之间持久保存状态
方法
方法返回值描述
show()void打开日历弹出窗口
hide()void关闭日历弹出窗口
focusIn()void将焦点设置到组件
focusOut()void移除组件焦点
navigateTo(view, date)void导航到特定视图和日期
currentView()string返回当前日历视图名称
getPersistData()string获取持久化状态数据
removeDate(dates)void从值中移除日期
destroy()void销毁组件
事件
事件参数类型描述
changeChangedEventArgs所选日期更改时触发
focusFocusEventArgs输入框获得焦点时触发
blurBlurEventArgs输入框失去焦点时触发
openPreventableEventArgs | PopupObjectArgs弹出窗口打开时触发
closePreventableEventArgs | PopupObjectArgs弹出窗口关闭时触发
clearedClearedEventArgs值清除时触发
createdObject组件创建时触发
destroyedObject组件销毁时触发
navigatedNavigatedEventArgs日历视图导航时触发
renderDayCellRenderDayCellEventArgs每个日期单元格渲染时触发
文档与导航指南

用户需要 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。

后续步骤:

DateTimePicker

Syncfusion React DateTimePickerComponent 将日期和时间选择整合到一个控件中。它提供日历 + 时间列表弹出窗口、可自定义的时间间隔、掩码、严格验证、时区处理、格式自定义以及完整的键盘辅助功能。

文档(请按顺序阅读以下参考资料)
快速入门(React + TypeScript)
  1. 安装软件包:
npm install @syncfusion/ej2-react-calendars
  1. 导入样式(在 index.css 或组件 CSS 中):
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-calendars/styles/material3.css';
  1. 最简可运行示例(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;
关键属性参考
属性类型默认值用途
valueDatenull当前选中的时间值
formatstring根据区域设置时间显示格式(例如,"HH:mm"、"hh:mm a")
minDate00:00可选时间的最小值
maxDate00:00可选时间的最大值
stepnumber30列表项之间的时间间隔(分钟)
enabledbooleantrue启用/禁用组件
readonlybooleanfalse只读状态(不可编辑)
placeholderstring-输入框占位文本
openOnFocusbooleanfalse输入框获得焦点时打开弹出窗口
enableMaskbooleanfalse启用掩码输入模式
enableRtlbooleanfalse启用从右到左的布局
strictModebooleanfalse验证输入并将其限制为有效时间
showClearButtonbooleantrue显示/隐藏清除按钮
fullScreenModebooleanfalse移动端全屏模式
cssClassstring-用于设置样式的自定义 CSS 类
floatLabelTypestringNever浮动标签位置
allowEditbooleantrue允许手动编辑输入
localestring'en-US'用于时间格式化的区域设置
scrollToDate-弹出窗口中的默认滚动位置
widthstring/number-组件宽度
zIndexnumber1000弹出窗口的 Z-index
serverTimezoneOffsetnumber-用于处理的服务器时区偏移量
htmlAttributesobject{}自定义 HTML 属性

后续步骤:

评论

支持 Markdown