关于 syncfusion-angular-calendars
面向 Angular 开发者的 Syncfusion Calendar 和 DatePicker 实现指南,涵盖日期选择、导航、事件、表单集成与样式定制。也说明多语言、无障碍和日期约束等配置方式。
主要功能
- 01单日期与多日期选择
- 02月、年和十年视图导航
- 03事件处理与日期管理方法
- 04本地化、RTL 与键盘操作
- 05表单集成和日期范围校验
- 06自定义日期单元格样式
适用场景
- 01在活动预订表单中设置日期范围
- 02显示并选择多个会议日期
- 03构建支持键盘操作的日期表单
- 04为不同地区配置日期格式
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ syncfusion/ angular-ui-components-skills --skill syncfusion-angular-calendars安装后在 Claude Code 中输入/syncfusion-angular-calendars确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/calendar-accessibility-and-globalization.mdcalendar-api-reference.mdcalendar-date-selection.mdcalendar-events-and-methods.mdcalendar-getting-started.mdcalendar-navigation.mdcalendar-styling-and-customization.mdcalendar-views.mddatepicker-accessibility-and-forms.mddatepicker-advanced-patterns.mddatepicker-date-formats-and-parsing.mddatepicker-date-range-and-validation.mddatepicker-date-views-and-navigation.mddatepicker-getting-started.mddatepicker-globalization-and-localization.mddatepicker-masking-and-editing.mddatepicker-styling-and-customization.mddatepicker-testing-guide.mddaterangepicker-api-reference.mddaterangepicker-date-formatting-and-constraints.mddaterangepicker-date-range-selection.mddaterangepicker-events-and-methods.mddaterangepicker-getting-started.mddaterangepicker-globalization-and-localization.mddaterangepicker-keyboard-navigation-and-accessibility.mddaterangepicker-preset-ranges.mddaterangepicker-styling-and-customization.mddatetimepicker-accessibility-and-globalization.mddatetimepicker-advanced-features.mddatetimepicker-api-reference.md详细介绍
实现 Syncfusion Angular 日历
日历
本指南全面介绍如何在 Angular 应用中实现 Syncfusion Essential JS 2 Calendar 组件。了解如何创建日期选择器、管理日历视图、处理事件以及自定义样式。
日历概述
Syncfusion Angular Calendar 组件是一种日期选择控件,提供以下功能:
- 多种日历视图: 月(默认)、年和十年视图,并支持流畅导航
- 日期选择模式: 使用
isMultiSelection属性选择单个日期或多个日期 - 导航控制: 使用
navigateTo()方法以编程方式切换视图 - 日期操作方法: 使用
addDate()和removeDate()管理多选 - 全面的事件系统: change、created、navigated、renderDayCell、destroyed 事件
- 本地化支持: 特定区域设置的格式、日期标题格式、每周首日
- 无障碍访问: 完全符合 WCAG 2.2 标准,支持键盘导航和 RTL
- 丰富的自定义选项: CSS 类、自定义渲染、日期单元格自定义
- 持久化: 可选择在页面重新加载后保留状态
软件包: @syncfusion/ej2-angular-calendars
文档导航
根据具体需求阅读以下参考资料:
入门指南
📄 阅读: references/getting-started.md
- 软件包安装和模块设置
- CSS 主题导入和依赖项
- 基本日历实现
- Angular 中的组件初始化
- 运行和测试设置
日历视图
📄 阅读: references/calendar-views.md
- 月视图(默认显示)
- 年视图实现
- 十年视图实现
- 视图导航和切换
start属性的用法- 用于限制视图的
depth属性
日期选择
📄 阅读: references/date-selection.md
- 单日期选择
- 多日期选择(
isMultiSelection) - 用于单个日期的
value属性 - 用于多个日期的
values数组 - 日期最小值/最大值限制
- 日期范围验证
事件和方法
📄 阅读: references/events-and-methods.md
- 事件处理程序(change、created、navigated、renderDayCell、destroyed)
- 用于多选的
addDate()方法 - 用于多选的
removeDate()方法 - 用于编程式导航的
navigateTo() - 用于获取当前视图的
currentView() - 用于获取持久化数据的
getPersistData() - 用于销毁日历控件的
destroy() - 使用 RenderDayCell 自定义日期样式
日历导航
📄 阅读: references/calendar-navigation.md
- 月份导航控件
- 年视图和十年视图切换
- “今天”按钮(
showTodayButton) firstDayOfWeek属性- 周数显示(
weekNumber) - 键盘快捷键和导航
无障碍访问和全球化
📄 阅读: references/accessibility-and-globalization.md
- 符合 WCAG 2.2 和 Section 508 标准
- WAI-ARIA 属性和角色
- 键盘导航(方向键、回车键、空格键)
- 兼容屏幕阅读器
- 本地化(locale 属性)
- 日期标题格式(短、窄、缩写、完整)
- RTL(从右到左)支持
样式和自定义
📄 阅读: references/styling-and-customization.md
- CSS 类自定义(.e-calendar、.e-day-cell、.e-selected)
- 主题选择(Material、Bootstrap、Tailwind、Fabric)
- 深色模式实现
- 通过 renderDayCell 自定义日期单元格样式
- 禁用日期的样式
- 悬停和焦点状态
API 参考
📄 阅读: references/api-reference.md
- 完整的属性参考(value、values、isMultiSelection、min、max、start、depth、showTodayButton、locale、dayHeaderFormat、weekNumber、weekRule、firstDayOfWeek、cssClass、enableRtl、enabled、calendarMode、keyConfigs、enablePersistence、serverTimezoneOffset)
- 所有方法签名及示例(addDate、removeDate、navigateTo、currentView、getPersistData、destroy)
- 事件参数类型(ChangedEventArgs、NavigatedEventArgs、RenderDayCellEventArgs)
- 键盘快捷键的按键配置
- 日历模式(Gregorian、Islamic)
- 返回类型及说明
快速入门示例
// app.component.ts
import { Component } from '@angular/core';
import { ChangedEventArgs } from '@syncfusion/ej2-calendars';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Single date selection
selectedDate: Date = new Date();
// Multiple date selection
selectedDates: Date[] = [
new Date(2026, 2, 15),
new Date(2026, 2, 20),
new Date(2026, 2, 25)
];
// Calendar configuration
minDate: Date = new Date(2020, 0, 1);
maxDate: Date = new Date(2030, 11, 31);
// Event handler
onCalendarChange(args: ChangedEventArgs): void {
console.log('Selected date:', args.value);
}
}
<div style="padding: 20px; font-family: Arial, sans-serif;">
<h2>Single Date Selection</h2>
<ejs-calendar
[(ngModel)]="selectedDate"
[min]="minDate"
[max]="maxDate"
(change)="onCalendarChange($event)">
</ejs-calendar>
<p>Selected: {{ selectedDate | date:'medium' }}</p>
<h2>Multiple Date Selection</h2>
<ejs-calendar
[(ngModel)]="selectedDates"
[isMultiSelection]="true"
[showTodayButton]="true">
</ejs-calendar>
<p>Selected dates: {{ selectedDates.length }} dates</p>
</div>
/* app.component.css */
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-calendars/styles/material3.css';
:host ::ng-deep .e-calendar {
margin: 20px 0;
}
:host ::ng-deep .e-selected {
background-color: #3f51b5;
color: white;
}
常见模式
模式 1:自定义日期范围(两个日历实例)
Calendar 组件没有内置的范围选择功能。使用两个独立的 Calendar 实例,结合 min/max 约束和 change 事件,实现自定义日期范围选择器:
export class AppComponent {
startDate: Date = new Date();
endDate: Date = new Date();
onStartDateChange(args: ChangedEventArgs): void {
this.startDate = args.value;
// Ensure end date is not before start date
if (this.endDate < this.startDate) {
this.endDate = this.startDate;
}
}
onEndDateChange(args: ChangedEventArgs): void {
this.endDate = args.value;
}
getDaysInRange(): number {
const timeDiff = this.endDate.getTime() - this.startDate.getTime();
return Math.ceil(timeDiff / (1000 * 3600 * 24)) + 1;
}
}
<ejs-calendar [(ngModel)]="startDate" (change)="onStartDateChange($event)"></ejs-calendar>
<ejs-calendar [(ngModel)]="endDate" [min]="startDate" (change)="onEndDateChange($event)"></ejs-calendar>
模式 2:禁用日期的日历
使用 renderDayCell 事件禁用特定日期(周末、节假日):
export class AppComponent {
holidays: Date[] = [
new Date(2026, 11, 25), // Christmas
new Date(2026, 0, 1), // New Year
];
onRenderDayCell(args: RenderDayCellEventArgs): void {
// Disable weekends
if (args.date.getDay() === 0 || args.date.getDay() === 6) {
args.isDisabled = true;
}
// Disable holidays
if (this.isHoliday(args.date)) {
args.isDisabled = true;
}
}
private isHoliday(date: Date): boolean {
return this.holidays.some(holiday =>
holiday.toDateString() === date.toDateString()
);
}
}
模式 3:使用添加/移除功能进行多选
以编程方式管理多个选中的日期:
export class AppComponent {
@ViewChild('calendar') calendarRef!: CalendarComponent;
selectedDates: Date[] = [];
addDateToSelection(date: Date): void {
// Check if already selected
if (!this.selectedDates.some(d =>
d.toDateString() === date.toDateString())) {
this.calendarRef.addDate(date);
}
}
removeDateFromSelection(date: Date): void {
this.calendarRef.removeDate(date);
}
clearAllDates(): void {
if (this.selectedDates.length > 0) {
this.calendarRef.removeDate(this.selectedDates);
}
}
}
模式 4:年份/十年视图导航
实现导航到不同日历视图的功能:
export class AppComponent {
@ViewChild('calendar') calendarRef!: CalendarComponent;
navigateToYear(year: number): void {
const dateInYear = new Date(year, 0, 1);
this.calendarRef.navigateTo('Year', dateInYear);
}
navigateToDecade(startYear: number): void {
const dateInDecade = new Date(startYear, 0, 1);
this.calendarRef.navigateTo('Decade', dateInDecade);
}
getCurrentView(): string {
return this.calendarRef.currentView();
}
}
模式 5:响应式表单集成
将 Calendar 与 Angular Reactive Forms 集成:
export class AppComponent implements OnInit {
dateForm: FormGroup;
constructor(private fb: FormBuilder) {
this.dateForm = this.fb.group({
eventDate: [new Date(), Validators.required],
eventName: ['', Validators.required]
});
}
ngOnInit(): void {
// Subscribe to date changes
this.dateForm.get('eventDate')?.valueChanges.subscribe(date => {
console.log('Event date changed:', date);
});
}
submitForm(): void {
if (this.dateForm.valid) {
console.log('Form values:', this.dateForm.value);
}
}
}
<form [formGroup]="dateForm" (ngSubmit)="submitForm()">
<div>
<label for="eventDate">Event Date:</label>
<ejs-calendar
id="eventDate"
formControlName="eventDate">
</ejs-calendar>
</div>
<div>
<label for="eventName">Event Name:</label>
<input
id="eventName"
type="text"
formControlName="eventName">
</div>
<button type="submit" [disabled]="!dateForm.valid">Submit</button>
</form>
关键属性参考
| 属性 | 类型 | 说明 | 示例 |
|---|---|---|---|
value | Date | 单个选中的日期 | [value]="selectedDate" |
values | Date[] | 多个选中的日期 | [values]="selectedDates" |
isMultiSelection | boolean | 启用多日期选择 | [isMultiSelection]="true" |
min | Date | 可选日期的下限 | [min]="minDate" |
max | Date | 可选日期的上限 | [max]="maxDate" |
start | CalendarView | 初始视图(月/年/十年) | start="Month" |
depth | CalendarView | 最大视图级别 | depth="Month" |
showTodayButton | boolean | 显示“今天”按钮 | [showTodayButton]="true" |
locale | string | 区域/语言代码 | locale="fr-FR" |
dayHeaderFormat | DayHeaderFormats | 星期格式(短/窄/缩写/完整) | dayHeaderFormat="Abbreviated" |
weekNumber | boolean | 显示周数 | [weekNumber]="true" |
weekRule | WeekRule | 一年中第一周的规则(FirstDay/FirstFullWeek/FirstFourDayWeek) | weekRule="FirstFourDayWeek" |
firstDayOfWeek | number | 一周的第一天(0=周日,1=周一) | [firstDayOfWeek]="1" |
cssClass | string | 自定义 CSS 类 | cssClass="custom-calendar" |
enableRtl | boolean | 启用 RTL 布局 | [enableRtl]="true" |
enabled | boolean | 启用/禁用组件 | [enabled]="true" |
calendarMode | CalendarType | 日历模式(Gregorian/Islamic) | calendarMode="Islamic" |
keyConfigs | { [key: string]: string } | 自定义键盘快捷键 | [keyConfigs]="keyConfigs" |
enablePersistence | boolean | 在页面重新加载后保留状态 | [enablePersistence]="true" |
serverTimezoneOffset | number | null | 用于初始日期处理的服务器时区偏移量 | [serverTimezoneOffset]="330" |
常见用例
用例 1:活动预订系统
用例 2:会议日程
用例 3:无障碍预订表单
- 在表单中集成日历并支持键盘导航
- 兼容屏幕阅读器,符合 WCAG 2.2 标准
- 解决方案:使用 Reactive Forms + 日历事件
- 参考:无障碍与全球化
用例 4:国际化日期选择器
- 支持多种语言和日期格式
- 为阿拉伯语、希伯来语显示 RTL 布局
- 解决方案:使用 locale 属性和本地化功能
- 参考:无障碍与全球化
用例 5:动态日期限制
DatePicker
Syncfusion Angular DatePicker 提供直观易用的日历界面,用于选择单个日期,并支持格式化、验证、日期范围以及完整的无障碍功能(WCAG 2.2)。本技能将引导你了解所有基本实现模式和高级功能。
组件概述
DatePicker 将文本输入框与弹出式日历选择器结合起来。用户可以直接输入日期,也可以通过日历进行选择。主要功能:
- 日期选择:通过日历 UI 或文本输入框选择
- 多种日期格式(适配区域设置、自定义模式)
- 日期范围验证(最小值/最大值、严格模式)
- 输入掩码,帮助用户输入日期
- 多种日历视图(月 → 年 → 十年导航)
- 无障碍功能(WCAG 2.2、ARIA、键盘支持、RTL)
- 国际化(CLDR 数据、100 多种区域设置)
- 表单集成(FormValidator、响应式表单、模板驱动表单)
文档与导航指南
入门
📄 阅读:references/getting-started.md
- 面向 Angular 21+ 独立架构的安装与设置
- 软件包依赖项和导入
- DatePicker 基本实现
- CSS 主题导入
- 最简可运行示例
日期格式与解析
📄 阅读:references/date-formats-and-parsing.md
- 标准日期格式模式(yyyy-MM-dd、dd/MM/yyyy 等)
- 区域设置专属的默认格式
- 创建自定义日期格式
- parseDate 和 formatDate 方法
- 动态切换格式
日期范围与验证
📄 阅读:references/date-range-and-validation.md
- 设置日期范围限制(min/max 属性)
- 处理超出范围的日期和错误状态
- 空日期验证和 strictMode
- 检测无效日期
- 实际应用中的日期限制模式
日期视图与导航
📄 阅读:references/date-views-and-navigation.md
- 配置起始视图(月/年/十年)
- 限制深度视图以限制选择范围
- 在不同日历视图之间导航
- 月份和年份选择模式
- 不同视图配置的适用场景
掩码与编辑
📄 阅读: references/masking-and-editing.md
- 启用日期输入掩码,引导用户输入
- 基于日期格式的掩码模式
- 掩码输入中的键盘导航(上/下/左/右箭头)
- 自定义掩码占位符
- 支持区域设置的掩码占位文本
样式与自定义
📄 阅读: references/styling-and-customization.md
- 自定义包装元素和输入元素的 CSS
- DatePicker 图标的样式与自定义
- 移动设备上的全屏模式
- 占位符和只读状态自定义
- 深色模式与 Theme Studio 集成
无障碍与表单
📄 阅读: references/accessibility-and-forms.md
- 符合 WCAG 2.2 和无障碍标准
- ARIA 属性(aria-expanded、aria-disabled、aria-activedescendant)
- 键盘导航支持(箭头键、Enter、Escape)
- 屏幕阅读器支持和语义化标记
- 集成 FormValidator 进行日期验证
- 响应式表单和模板驱动表单模式
- 自定义验证规则
全球化与本地化
📄 阅读: references/globalization-and-localization.md
- 加载 CLDR 数据,实现特定区域的格式化
- 区域设置感知的日期解析和格式化
- 区域设置配置和 L10n 设置
- 按区域设置确定每周第一天(周数据)
- 支持从右到左(RTL)的语言
- 多语言示例
- 支持时区的日期处理
测试与质量保证
📄 阅读: references/testing-guide.md
- 使用 Jasmine/Karma 进行单元测试:解析、验证器、事件
- 使用 Cypress 进行 E2E 测试:日历交互、表单流程
- 使用 axe-core 进行无障碍测试,并检查键盘导航
高级模式
📄 阅读: references/advanced-patterns.md
- 级联日期选择器(依赖可用性)
- 由业务逻辑驱动的动态日期范围
- 禁用/不可用日期及重复日期处理
- 高级场景的测试和验证模式
快速入门示例
在 Angular 21+ 独立组件中实现基础 DatePicker:
import { Component } from '@angular/core';
import { DatePickerModule } from '@syncfusion/ej2-angular-calendars';
@Component({
selector: 'app-datepicker-demo',
standalone: true,
imports: [DatePickerModule],
template: `
<ejs-datepicker
placeholder="Select date"
[(ngModel)]="selectedDate"
(change)="onDateChange($event)">
</ejs-datepicker>
<p>Selected: {{ selectedDate | date:'fullDate' }}</p>
`
})
export class DatePickerDemoComponent {
selectedDate: Date | null = null;
onDateChange(event: any) {
console.log('Date changed:', event.value);
}
}
设置步骤:
- 安装
@syncfusion/ej2-angular-calendars包 - 在组件中导入
DatePickerModule - 添加带有属性的
<ejs-datepicker>元素 - 使用
[(ngModel)](双向绑定)绑定到组件变量
运行效果:
- DatePicker 会显示日历图标
- 单击以打开弹出日历
- 从日历中选择日期或直接输入
- 所选日期会更新组件变量
- 选择日期时会触发 change 事件
常见模式
1. 日期范围验证
限制用户只能选择指定起止日期之间的日期:
minDate = new Date(2024, 0, 1); // Jan 1, 2024
maxDate = new Date(2024, 11, 31); // Dec 31, 2024
<ejs-datepicker
[min]="minDate"
[max]="maxDate"
placeholder="Select date in 2024">
</ejs-datepicker>
适用场景: 航班预订、酒店预订、预约安排
2. 自定义日期格式
以应用特定格式显示日期:
dateFormat = 'dd/MM/yyyy'; // European format
<ejs-datepicker
[format]="dateFormat"
placeholder="DD/MM/YYYY">
</ejs-datepicker>
3. 掩码日期输入
通过可视化掩码和箭头键导航引导用户输入:
<ejs-datepicker
[enableMask]="true"
[maskPlaceholder]="'day'"
format="dd/MM/yyyy">
</ejs-datepicker>
键盘导航: 上/下箭头可递增/递减各段,左/右箭头可在各段之间导航
4. 日期范围选择(带最小值/最大值)
在预订场景中禁止选择过去的日期:
minDate = new Date(); // Today
maxDate: Date;
constructor() {
// Set max to 90 days from today
this.maxDate = new Date();
this.maxDate.setDate(this.maxDate.getDate() + 90);
}
5. 响应式表单集成
带有响应式表单验证的 DatePicker:
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
export class FormComponent {
form = this.fb.group({
birthDate: [null, [Validators.required]],
});
constructor(private fb: FormBuilder) {}
}
<form [formGroup]="form">
<ejs-datepicker
formControlName="birthDate"
placeholder="Birth date">
</ejs-datepicker>
<span *ngIf="form.get('birthDate')?.hasError('required')">
Birth date is required
</span>
</form>
API 参考(属性、方法、事件)
属性
| 属性 | 类型 | 说明 |
|---|---|---|
allowEdit | boolean | 文本框是否可编辑(默认为 true) |
calendarMode | CalendarType | 日历类型(例如,公历、伊斯兰历) |
cssClass | string | 用于自定义样式的根 CSS 类 |
dayHeaderFormat | DayHeaderFormats | 日期标题格式(Short/Narrow/Abbreviated/Wide) |
depth | CalendarView | 允许的最深日历视图(Month/Year/Decade) |
enableMask | boolean | 启用带掩码的日期输入 |
enablePersistence | boolean | 在重新加载期间保留组件状态 |
enableRtl | boolean | 启用从右到左的渲染 |
enabled | boolean | 启用或禁用组件(设置为 false 可禁用) |
firstDayOfWeek | number | 一周的第一天(0-6) |
floatLabelType | FloatLabelType|string | 输入框的浮动标签行为 |
format | string|FormatObject | 值的显示格式 |
fullScreenMode | boolean | 在移动设备上以全屏模式显示弹出窗口 |
htmlAttributes | { [key:string]: string } | 根元素的其他 HTML 属性 |
inputFormats | string[]|FormatObject[] | 可接受的解析输入格式 |
keyConfigs | { [key:string]: string } | 自定义按键操作映射 |
locale | string | 覆盖全局区域设置(例如,'en-US') |
maskPlaceholder | MaskPlaceholderModel | 带掩码输入的占位文本 |
max | Date | 可选日期的上限 |
min | Date | 可选日期的下限 |
openOnFocus | boolean | 输入框获得焦点时打开弹出窗口 |
placeholder | string | 输入框占位文本 |
readonly | boolean | 将输入框设为只读(禁止输入) |
serverTimezoneOffset | number | 服务器时区偏移量(分钟,可选) |
showClearButton | boolean | 显示/隐藏清除图标 |
showTodayButton | boolean | 显示/隐藏弹出窗口中的“今天”按钮 |
start | CalendarView | 弹出窗口打开时的初始视图 |
strictMode | boolean | 强制执行严格解析/验证 |
value | Date | 选定的日期值 |
weekNumber | boolean | 在日历中显示周数 |
weekRule | WeekRule | 年份第一周的规则 |
width | number|string | 组件宽度 |
zIndex | number | 弹出窗口的 Z-index |
方法
currentView()— 返回当前日历视图名称destroy()— 销毁组件实例focusIn()— 聚焦输入框focusOut()— 使输入框失去焦点getPersistData()— 返回持久化属性字符串hide()— 隐藏日历弹出窗口navigateTo(view: CalendarView, date?: Date)— 导航到指定视图/日期removeDate(dates: Date|Date[])— 从值中移除日期show()— 显示日历弹出窗口
事件
blur— 输入框失去焦点时触发change— 值发生变化时触发(提供ChangedEventArgs)cleared— 使用清除按钮时触发close— 弹出窗口关闭时触发(可阻止)created— 组件创建生命周期事件destroyed— 组件销毁生命周期事件focus— 输入框获得焦点时触发navigated— 日历导航到其他视图时触发open— 弹出窗口打开时触发(可阻止)renderDayCell— 每个日期单元格渲染时触发(可用于禁用/自定义单元格)
常见用例
- 生日/出生日期选择: 使用最小值/最大值验证、带掩码的输入,以及十年视图起始页以便快速选择年份
- 会议日程安排: 日期范围(今天 + 90 天)、自定义工作日验证、表单集成
- 酒店/航班预订: 最小值/最大值日期、双向日期绑定,以及带验证的响应式表单
- 申请表单: 出生日期、许可证到期日、预约日期,并符合无障碍要求
- 国际化应用: 区域设置感知格式、RTL 支持、特定文化的日历
DateRangePicker
在 Angular 应用中实现 Syncfusion Essential JS 2 DateRangePicker 组件的综合指南。了解如何创建日期范围选择器、处理范围选择、管理事件和自定义样式。
DateRangePicker 概览
Syncfusion Angular DateRangePicker 组件是一款专用的日期选择控件,提供以下功能:
- 双日历显示: 同步日历,供用户选择开始日期和结束日期
- 预设范围: 预定义选项,例如“最近 7 天”“本月”“上月”“自定义”
- 范围验证: 最小/最大日期、禁用范围、必需的范围长度
- 日期格式: 可自定义日期格式,支持分隔符和格式模式
- 事件系统: created、destroyed、change、select、rangeSelected、open、close、renderDayCell 事件
- 键盘快捷键: 支持 Tab、方向键、Enter、Escape,提供完整的键盘无障碍支持
- 本地化支持: 特定区域设置的格式、日期标题和月份名称
- 无障碍功能: 完全符合 WCAG 2.2 标准,支持 ARIA 属性和屏幕阅读器
- 丰富的自定义选项: CSS 类、自定义模板、日期单元格渲染
- 移动设备优化: 触控友好界面、响应式设计、全屏模式
软件包: @syncfusion/ej2-angular-calendars
文档导航
根据具体需求阅读以下参考文档:
入门
📄 阅读: references/getting-started.md
- 软件包安装和模块设置
- CSS 主题导入和依赖项
- 基本的 DateRangePicker 实现
- 在 Angular 中初始化组件
- 开始日期和结束日期配置
- 运行和测试设置
日期范围选择
📄 阅读: references/date-range-selection.md
- 单击选择范围
- 依次选择日期(先单击开始日期,再单击结束日期)
- 日期范围值绑定(
startDate、endDate属性) - 最小/最大日期限制
- 范围验证和错误处理
- 禁用日期范围
- 清除选择
预设范围
📄 阅读: references/preset-ranges.md
- 预定义范围选项(最近 7 天、上月等)
- 自定义预设配置
- 以编程方式应用预设
- 动态生成预设
- 预设更改事件
- 将预设与限制条件结合使用
事件和方法
📄 阅读: references/events-and-methods.md
- 事件处理程序(change、select、rangeSelected、open、close)
- 范围选择事件详情(startDate、endDate、daySpan)
- 编程方法(show()、hide()、getSelectedRange())
- created 和 destroyed 生命周期事件
- 使用 RenderDayCell 自定义样式
- 方法返回类型和参数
日期格式和限制条件
📄 阅读: references/date-formatting-and-constraints.md
- 日期格式模式和分隔符
- 多种格式支持(format 和 inputFormats)
- 最小/最大日期限制
- 最小/最大天数验证
- 禁用日期配置
- 格式错误处理
- 特定区域设置的格式
键盘导航和无障碍功能
📄 阅读: references/keyboard-navigation-and-accessibility.md
- Tab 和 Shift+Tab 导航
- 使用方向键浏览日期
- 使用 Enter 选择并确认范围
- 使用 Escape 关闭选择器
- Alt 键快捷键
- 兼容屏幕阅读器
- ARIA 标签和角色
- 符合 WCAG 2.2 AA 标准
- 焦点管理
样式和自定义
📄 阅读: references/styling-and-customization.md
- CSS 类自定义(.e-daterangepicker、.e-calendar、.e-range-header)
- 主题选择(Material、Bootstrap、Tailwind、Fabric)
- 深色模式实现
- 使用 renderDayCell 自定义日期单元格样式
- 禁用日期样式
- 预设按钮样式
- 悬停和焦点状态
- 响应式布局自定义
全球化与本地化
📄 阅读: references/globalization-and-localization.md
- 用于日期格式设置的 Locale 属性
- RTL(从右向左)支持阿拉伯语、希伯来语
- 星期标题格式(短、窄、缩写、完整)
- 月份名称和星期名称本地化
- 自定义 Locale 支持
- 时区处理
- 日期格式本地化
API 参考
📄 阅读: references/api-reference.md
- 完整的属性参考及说明
- 所有方法签名及返回类型
- 事件参数类型和结构
- 类型接口(RangeEventArgs、NavigatingEventArgs 等)
- CSS 类和样式钩子
- 浏览器支持矩阵
快速入门示例
// app.component.ts
import { Component } from '@angular/core';
import { RangeEventArgs } from '@syncfusion/ej2-calendars';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Date range properties
startDate: Date = new Date(2026, 2, 1); // March 1, 2026
endDate: Date = new Date(2026, 2, 31); // March 31, 2026
// Constraints
minDate: Date = new Date(2020, 0, 1);
maxDate: Date = new Date(2030, 11, 31);
// Range display
selectedRange: string = '';
// Event handler
onRangeChange(args: RangeEventArgs): void {
console.log('Start Date:', args.startDate);
console.log('End Date:', args.endDate);
console.log('Days in range:', args.daySpan);
this.updateRangeDisplay();
}
updateRangeDisplay(): void {
if (this.startDate && this.endDate) {
const start = this.startDate.toLocaleDateString();
const end = this.endDate.toLocaleDateString();
this.selectedRange = `${start} - ${end}`;
}
}
}
<div style="padding: 20px; font-family: Arial, sans-serif;">
<h2>DateRangePicker Example</h2>
<div style="margin-bottom: 20px;">
<label for="dateRange">Select Date Range:</label>
<ejs-daterangepicker
id="dateRange"
placeholder="Select a date range"
[startDate]="startDate"
[endDate]="endDate"
[min]="minDate"
[max]="maxDate"
(change)="onRangeChange($event)">
</ejs-daterangepicker>
</div>
<div *ngIf="selectedRange" style="padding: 10px; background-color: #f0f0f0;">
<p><strong>Selected Range:</strong> {{ selectedRange }}</p>
</div>
</div>
/* app.component.css */
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-calendars/styles/material3.css';
:host ::ng-deep .e-daterangepicker {
margin: 10px 0;
width: 100%;
}
:host ::ng-deep .e-range-header {
background-color: #3f51b5;
color: white;
}
常见模式
模式 1:预设日期范围
用于常见日期范围的快速选择按钮:
export class AppComponent {
presets: any[] = [
{ label: 'Today', start: new Date(), end: new Date() },
{ label: 'Last 7 Days', start: this.getDateDaysAgo(7), end: new Date() },
{ label: 'Last 30 Days', start: this.getDateDaysAgo(30), end: new Date() },
{ label: 'This Month', start: this.getFirstDayOfMonth(), end: new Date() },
{ label: 'Last Month', start: this.getFirstDayOfLastMonth(), end: this.getLastDayOfLastMonth() }
];
startDate: Date = new Date();
endDate: Date = new Date();
selectPreset(preset: any): void {
this.startDate = preset.start;
this.endDate = preset.end;
}
private getDateDaysAgo(days: number): Date {
const date = new Date();
date.setDate(date.getDate() - days);
return date;
}
private getFirstDayOfMonth(): Date {
return new Date(new Date().getFullYear(), new Date().getMonth(), 1);
}
private getFirstDayOfLastMonth(): Date {
const date = new Date();
return new Date(date.getFullYear(), date.getMonth() - 1, 1);
}
private getLastDayOfLastMonth(): Date {
const date = new Date();
return new Date(date.getFullYear(), date.getMonth(), 0);
}
}
<div>
<div style="margin-bottom: 10px;">
<button *ngFor="let preset of presets"
(click)="selectPreset(preset)"
style="margin-right: 5px; padding: 8px 12px;">
{{ preset.label }}
</button>
</div>
<ejs-daterangepicker
[startDate]="startDate"
[endDate]="endDate">
</ejs-daterangepicker>
</div>
模式 2:日期范围验证
使用自定义约束验证日期范围:
export class AppComponent {
@ViewChild('daterangepicker') drp!: DateRangePickerComponent;
startDate: Date = new Date();
endDate: Date = new Date();
rangeError: string = '';
minDate: Date = new Date(2020, 0, 1);
maxDate: Date = new Date(2030, 11, 31);
minDays: number = 1; // At least 1 day
maxDays: number = 90; // At most 90 days
onRangeChange(args: RangeEventArgs): void {
this.rangeError = '';
// Validate date range
if (args.daySpan < this.minDays) {
this.rangeError = `Range must be at least ${this.minDays} day(s)`;
return;
}
if (args.daySpan > this.maxDays) {
this.rangeError = `Range cannot exceed ${this.maxDays} days`;
return;
}
this.startDate = args.startDate;
this.endDate = args.endDate;
}
isRangeValid(): boolean {
return this.rangeError === '';
}
}
模式 3:响应式表单集成
将 DateRangePicker 集成到响应式表单中:
export class AppComponent implements OnInit {
reportForm: FormGroup;
constructor(private fb: FormBuilder) {
this.reportForm = this.fb.group({
reportName: ['', Validators.required],
startDate: [new Date(2026, 0, 1), Validators.required],
endDate: [new Date(), Validators.required]
});
}
ngOnInit(): void {
this.reportForm.get('startDate')?.valueChanges.subscribe(date => {
console.log('Start date changed:', date);
this.validateDateRange();
});
this.reportForm.get('endDate')?.valueChanges.subscribe(date => {
console.log('End date changed:', date);
this.validateDateRange();
});
}
validateDateRange(): void {
const start = this.reportForm.get('startDate')?.value;
const end = this.reportForm.get('endDate')?.value;
if (start && end && start > end) {
this.reportForm.get('endDate')?.setErrors({ 'invalidRange': true });
} else {
this.reportForm.get('endDate')?.setErrors(null);
}
}
submitForm(): void {
if (this.reportForm.valid) {
console.log('Form values:', this.reportForm.value);
}
}
}
<form [formGroup]="reportForm" (ngSubmit)="submitForm()">
<div>
<label>Report Name:</label>
<ejs-textbox
formControlName="reportName"
placeholder="Enter report name">
</ejs-textbox>
</div>
<div>
<label>Report Period:</label>
<ejs-daterangepicker
[formControl]="reportForm.get('startDate')"
[endDate]="reportForm.get('endDate')?.value">
</ejs-daterangepicker>
</div>
<button type="submit" [disabled]="!reportForm.valid">Generate Report</button>
</form>
模式 4:动态范围约束
根据业务逻辑更新范围约束:
export class AppComponent {
startDate: Date = new Date();
endDate: Date = new Date();
// Dynamic constraints
minDate: Date = new Date();
maxDate: Date = new Date();
reportType: string = 'daily';
onReportTypeChange(type: string): void {
this.reportType = type;
this.updateConstraints();
}
private updateConstraints(): void {
const today = new Date();
switch (this.reportType) {
case 'daily':
// Last 7 days only
this.minDate = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
this.maxDate = today;
break;
case 'monthly':
// Last 12 months
this.minDate = new Date(today.getFullYear() - 1, today.getMonth(), 1);
this.maxDate = today;
break;
case 'yearly':
// Last 5 years
this.minDate = new Date(today.getFullYear() - 5, 0, 1);
this.maxDate = today;
break;
}
}
}
模式 5:禁用日期范围
禁用特定日期范围(节假日、不可用日期):
export class AppComponent {
disabledRanges: Array<{start: Date, end: Date}> = [
{ start: new Date(2026, 11, 20), end: new Date(2026, 11, 31) }, // Christmas season
{ start: new Date(2026, 0, 1), end: new Date(2026, 0, 3) } // New Year
];
startDate: Date = new Date();
endDate: Date = new Date();
onRenderDayCell(args: RenderDayCellEventArgs): void {
// Disable dates in disabled ranges
for (const range of this.disabledRanges) {
if (args.date >= range.start && args.date <= range.end) {
args.isDisabled = true;
break;
}
}
}
}
关键属性参考
| 属性 | 类型 | 描述 | 示例 |
|---|---|---|---|
startDate | Date | 范围的开始日期 | [startDate]="start" |
endDate | Date | 范围的结束日期 | [endDate]="end" |
value | Date[] 或 DateRange | 选定的日期范围(数组或对象) | [(ngModel)]="dateRange" |
min | Date | 可选的最早日期 | [min]="minDate" |
max | Date | 可选的最晚日期 | [max]="maxDate" |
minDays | number | 范围内的最少天数 | [minDays]="1" |
maxDays | number | 范围内的最多天数 | [maxDays]="90" |
format | string | 日期显示格式 | format="dd/MM/yyyy" |
separator | string | 范围分隔符 | separator=" to " |
placeholder | string | 占位文本 | placeholder="Select date range" |
presets | PresetsModel[] | 预定义的范围选项 | [presets]="presets" |
strictMode | boolean | 严格日期验证 | [strictMode]="true" |
readonly | boolean | 只读输入字段 | [readonly]="false" |
enabled | boolean | 启用/禁用组件 | [enabled]="true" |
locale | string | 区域设置/语言代码 | locale="en-US" |
enableRtl | boolean | 启用 RTL 布局 | [enableRtl]="false" |
cssClass | string | 自定义 CSS 类 | cssClass="custom-drp" |
width | number | string | 组件宽度 | width="300px" |
allowEdit | boolean | 允许手动输入文本 | [allowEdit]="true" |
openOnFocus | boolean | 输入框获得焦点时打开选择器 | [openOnFocus]="true" |
showClearButton | boolean | 显示清除按钮 | [showClearButton]="true" |
depth | CalendarView | 日历视图深度 | depth="Month" |
常见用例
用例 1:选择报表日期范围
- 用户为生成报表选择日期范围
- 应用最小/最大日期限制
- 支持预设范围(最近 7 天、上个月等)
- 解决方案:将 startDate/endDate 与预设范围及最小/最大限制结合使用
- 参考:预设范围 + 日期格式与限制
用例 2:预订系统日期范围
- 选择预订的入住和退房日期
- 禁用过去的日期和不可预订日期
- 显示范围内的天数
- 解决方案:使用最小日期限制,通过 renderDayCell 渲染禁用日期范围,并计算 daySpan
- 参考:日期范围选择 + 事件与方法
用例 3:分析日期筛选器
用例 4:无障碍表单字段
- 在表单中集成 DateRangePicker,并全面支持键盘无障碍操作
- 兼容屏幕阅读器,符合 WCAG 2.2 标准
- 解决方案:与 Reactive Forms 配合使用,并设置合适的 ARIA 标签
- 参考:键盘导航与无障碍
用例 5:国际化日期选择器
- 支持多种语言和日期格式
- 支持阿拉伯语、希伯来语的 RTL 布局
- 使用特定区域设置的格式
- 解决方案:使用 locale 属性并自定义格式
- 参考:全球化与本地化
DatetimePicker
本指南全面介绍如何在 Angular 应用中实现 Syncfusion Essential JS 2 DatetimePicker 组件。了解如何创建日期和时间选择界面、管理日历和时间选择器、处理事件并自定义样式。
DatetimePicker 概述
Syncfusion Angular DatetimePicker 组件是一款组合式日期和时间选择控件,提供以下功能:
- 集成日期与时间选择: 日期使用日历弹出窗口,时间使用时间选择器下拉菜单
- 灵活的格式设置: 自定义日期格式、时间格式,以及适配区域设置的格式
- 日历视图: 月(默认)、年和十年视图,并支持流畅导航
- 时间间隔: 可配置时间选择步长间隔(15、30、60 分钟等)
- 范围限制: 最小/最大日期和最小/最大时间,并支持严格验证
- 全面的事件系统: change、focus、blur、open、close、created、destroyed、navigated、renderDayCell 事件
- 掩码输入支持: 可选的掩码输入格式,便于引导用户输入
- 持久化与 RTL: 跨重新加载保存状态,并支持从右向左的语言
- 高级功能: 严格模式验证、浮动标签、键盘自定义、时区支持
- 无障碍: 全面符合 WCAG 2.2 标准,支持键盘导航和 WAI-ARIA
- 主题支持: Material、Bootstrap、Tailwind、Fabric,并提供浅色/深色变体
- 移动设备优化: 在移动设备上使用全屏模式,提供便于触控的界面
程序包: @syncfusion/ej2-angular-datetimepickers
文档导航
根据具体需求阅读以下参考资料:
快速入门
📄 阅读: references/getting-started.md
- 通过 npm 和 ng add 安装程序包
- 配置 NgModule 与 Standalone 组件
- 导入 CSS 主题和依赖项
- 实现基本的 datetimepicker
- 初始化组件并运行应用
- 设置开发服务器
基本实现
📄 阅读: references/basic-implementation.md
- 使用 ngModel 的简单日期时间选择器
- 双向数据绑定模式
- 只读和禁用状态
- 基本验证和约束
- 事件处理基础
- 使用 ViewChild 访问组件
日期和时间配置
📄 阅读: references/date-time-configuration.md
- 自定义日期格式(format 属性)
- 配置时间格式(timeFormat 属性)
- 处理 ISO 日期字符串
- 日期范围约束(最小/最大日期)
- 时间范围约束(minTime/maxTime)
- 解析多种输入格式(inputFormats)
日历和时间视图
📄 阅读: references/calendar-and-time-views.md
- 日历视图模式(月、年、十年)
- 用于控制视图的 start 和 depth 属性
- 时间选择器弹出窗口配置
- 时间步长间隔和粒度
- 时间滚动的 ScrollTo 位置
- “今天”按钮和清除按钮的行为
事件和回调
📄 阅读: references/events-and-callbacks.md
- 带有 ChangedEventArgs 的 Change 事件
- 焦点/失焦事件处理
- 打开/关闭弹出窗口事件
- 创建/销毁生命周期事件
- 用于日历导航的 Navigate 事件
- 使用 RenderDayCell 自定义日期样式
- 使用清除按钮时触发的 Cleared 事件
方法和命令式访问
📄 阅读: references/methods-and-imperative-access.md
- ViewChild 访问和组件引用
- 使用 currentView() 获取当前日历视图
- 使用 navigateTo() 进行编程式导航
- 使用 focusIn/focusOut 管理焦点
- 使用 destroy() 清理并释放资源
- 使用 getPersistData() 持久化状态
高级功能
📄 阅读: references/advanced-features.md
- 带有掩码占位符的掩码输入模式
- 页面重新加载后保留状态
- RTL(从右到左)语言支持
- 浮动标签类型和行为
- 严格模式验证和错误状态
- 键盘快捷键和按键配置
- 时区偏移处理
- 移动设备全屏模式
- 清除按钮的显示和行为
样式和自定义
📄 阅读: references/styling-and-customization.md
- CSS 类自定义(cssClass 属性)
- 主题选择和切换
- 深色模式实现
- 组件宽度和 z-index 配置
- 注入 HTML 属性(htmlAttributes)
- 日历模式选择(公历或伊斯兰历)
- 日期标题格式选项
- 禁用日期和样式状态
无障碍访问和全球化
📄 阅读: references/accessibility-and-globalization.md
- 符合 WCAG 2.2 和 Section 508 标准
- WAI-ARIA 属性和角色
- 键盘导航(方向键、回车、空格、Esc)
- 屏幕阅读器兼容性和播报
- 本地化和 locale 属性用法
- 日期标题格式变化
- 自定义每周首日
- 周数和周规则
- 支持 RTL 文本方向
API 参考
📄 阅读: references/api-reference.md
- 完整的属性参考,包含类型和默认值
- 所有方法签名,包含参数和返回类型
- 所有事件及其事件参数类型
- 属性说明和使用场景
- 方法示例和常见模式
- 类型接口和枚举
- 用于键盘快捷键的按键配置
- 全面的逐项属性指南
快速入门示例
// app.component.ts
import { Component } from '@angular/core';
import { ChangedEventArgs } from '@syncfusion/ej2-datetimepickers';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Simple datetime value
dateTimeValue: Date = new Date();
// Configuration
minDate: Date = new Date(2020, 0, 1);
maxDate: Date = new Date(2030, 11, 31);
dateFormat: string = 'dd/MM/yyyy hh:mm a';
timeFormat: string = 'hh:mm a';
// Event handler
onDateTimeChange(args: ChangedEventArgs): void {
console.log('Selected DateTime:', args.value);
console.log('Event Type:', args.type);
}
onPopupOpen(): void {
console.log('Popup opened');
}
onPopupClose(): void {
console.log('Popup closed');
}
}
<div style="padding: 20px;">
<h2>Select Date & Time</h2>
<ejs-datetimepicker
id="datetimepicker"
[value]="dateTimeValue"
[format]="dateFormat"
[timeFormat]="timeFormat"
[min]="minDate"
[max]="maxDate"
placeholder="Select date and time"
(change)="onDateTimeChange($event)"
(open)="onPopupOpen()"
(close)="onPopupClose()">
</ejs-datetimepicker>
<p *ngIf="dateTimeValue">
Selected: {{ dateTimeValue | date:'medium' }}
</p>
</div>
常见模式
模式 1:日期时间范围选择
选择预约、预订或活动的开始和结束日期时间:
export class AppComponent {
startDateTime: Date = new Date();
endDateTime: Date = new Date(Date.now() + 3600000); // +1 hour
onStartChange(args: ChangedEventArgs): void {
// Ensure end is after start
if (this.endDateTime <= args.value) {
this.endDateTime = new Date((args.value as Date).getTime() + 3600000);
}
}
}
模式 2:仅限营业时间
将时间选择限制在营业时间内(上午 9 点至下午 5 点):
export class AppComponent {
minTime: Date = new Date(2026, 2, 24, 9, 0); // 9:00 AM
maxTime: Date = new Date(2026, 2, 24, 17, 0); // 5:00 PM
datetimeValue: Date = new Date(2026, 2, 24, 10, 0);
}
<ejs-datetimepicker
[value]="datetimeValue"
[minTime]="minTime"
[maxTime]="maxTime"
timeFormat="hh:mm a">
</ejs-datetimepicker>
模式 3:使用掩码输入引导用户输入
使用掩码输入引导用户按照日期时间格式输入:
export class AppComponent {
datetimeValue: Date;
maskPlaceholder = {
day: 'dd',
month: 'mm',
year: 'yyyy',
hour: 'hh',
minute: 'mm',
second: 'ss'
};
}
<ejs-datetimepicker
[value]="datetimeValue"
[enableMask]="true"
[maskPlaceholder]="maskPlaceholder"
format="dd/MM/yyyy hh:mm:ss">
</ejs-datetimepicker>
模式 4:集成响应式表单
将 datetimepicker 集成到 Angular 响应式表单中:
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
export class AppComponent {
appointmentForm: FormGroup;
constructor(private fb: FormBuilder) {
this.appointmentForm = this.fb.group({
appointmentDateTime: [
new Date(),
[Validators.required]
]
});
}
submitForm(): void {
if (this.appointmentForm.valid) {
console.log(this.appointmentForm.value);
}
}
}
<form [formGroup]="appointmentForm">
<ejs-datetimepicker
formControlName="appointmentDateTime"
format="dd/MM/yyyy hh:mm a">
</ejs-datetimepicker>
<button (click)="submitForm()" [disabled]="!appointmentForm.valid">
Submit
</button>
</form>
模式 5:禁用日期
禁用周末和指定日期:
export class AppComponent {
datetimeValue: Date;
onRenderDayCell(args: RenderDayCellEventArgs): void {
// Disable weekends (0 = Sunday, 6 = Saturday)
if ((args.date as Date).getDay() === 0 || (args.date as Date).getDay() === 6) {
args.isDisabled = true;
}
// Disable specific dates
const disabledDates = [5, 15, 25]; // 5th, 15th, 25th of each month
if (disabledDates.includes((args.date as Date).getDate())) {
args.isDisabled = true;
}
}
}
<ejs-datetimepicker
[value]="datetimeValue"
(renderDayCell)="onRenderDayCell($event)">
</ejs-datetimepicker>
关键属性参考
| 属性 | 类型 | 用途 |
|---|---|---|
value | Date | 用于双向绑定的所选日期时间值 |
format | string | 日期显示格式(例如,'dd/MM/yyyy hh:mm a') |
timeFormat | string | 弹出窗口中的时间显示格式(例如,'hh:mm a') |
min | Date | 可选择的最早日期 |
max | Date | 可选择的最晚日期 |
minTime | Date | 可选择的最早时间 |
maxTime | Date | 可选择的最晚时间 |
step | number | 时间间隔(分钟)(15、30、60) |
enabled | boolean | 启用/禁用组件 |
readonly | boolean | 将输入设为只读(仅可从弹出窗口选择) |
placeholder | string | 输入框中的占位文本 |
enableMask | boolean | 启用掩码输入模式 |
strictMode | boolean | 仅允许有效值 |
enableRtl | boolean | 支持从右向左书写的语言 |
enablePersistence | boolean | 在页面重新加载后保留值 |
start | CalendarView | 初始日历视图(Month/Year/Decade) |
depth | CalendarView | 日历视图的最高层级 |
locale | string | 格式化所用的区域设置(例如,'en-US'、'de-DE') |
常见用例
预约系统
- 使用日期范围选择,并限制营业时间
- 根据 min/max time 显示可用时段
- 使用必填验证器处理表单验证
- 显示所选日期时间的确认信息
活动安排
- 选择活动的开始和结束日期时间
- 使用 renderDayCell 禁用周末
- 使用 step 设置常用时长间隔(30、60 分钟)
- 格式化输出以便提交至 API
班次管理
- 选择班次的开始和结束时间
- 应用班次时间限制(最早/最晚时间)
- 处理日期切换(跨午夜的班次)
- 支持多个时区偏移量
计费与开票
- 选择发票日期和时间
- 仅允许选择过去的日期
- 按用户的区域设置格式显示
- 使用 ISO 格式导出
后续步骤
- 从入门指南开始 → 安装并配置组件
- 构建基本实现 → 创建简单的日期时间选择器
- 添加事件处理 → 响应用户交互
- 实现高级功能 → 添加掩码输入、持久化和 RTL
- 自定义外观 → 应用主题和自定义样式
- 确保无障碍访问 → 支持键盘和屏幕阅读器
- 参考 API → 根据需要查阅完整的 API 文档
TimePicker
这是一份全面的指南,介绍如何在 Angular 应用中实现 Syncfusion Essential JS 2 TimePicker 组件。了解如何创建时间选择界面、管理时间输入、处理事件以及自定义样式。
TimePicker 概述
Syncfusion Angular TimePicker 组件是一款专用的时间选择控件,提供以下功能:
- 时间选择: 提供可配置时间间隔的弹出列表,供用户选择
- 灵活格式化: 支持自定义时间格式、骨架选项和基于区域设置的格式化
- 时间间隔: 支持配置时间选择步长(15、30、60 分钟等)
- 范围限制: 支持最小/最大时间,并进行严格验证和边界限制
- 全面的事件系统: change、focus、blur、open、close、created、destroyed、cleared、itemRender 事件
- 掩码输入支持: 可选的掩码输入格式,引导用户输入
- 持久化和 RTL: 支持跨重新加载保存状态,以及从右到左语言
- 高级功能: 严格模式验证、浮动标签、键盘自定义、时区支持
- 无障碍访问: 完全符合 WCAG 2.2 标准,支持键盘导航和 WAI-ARIA
- 主题支持: Material、Bootstrap、Tailwind、Fabric,提供浅色/深色变体
- 针对移动设备优化: 移动设备上的全屏模式,触控友好的界面
包: @syncfusion/ej2-angular-calendars
文档导航
根据具体需求阅读以下参考文档:
开始使用
📄 阅读: references/getting-started.md
- 通过 npm 和 ng add 安装包
- NgModule 与 Standalone 组件设置
- CSS 主题导入和依赖项
- 基本的 timepicker 实现
- 组件初始化和运行应用程序
- 开发服务器设置
基本实现
📄 阅读: references/basic-implementation.md
- 使用 ngModel 的简单时间选择器
- 双向数据绑定模式
- 只读和禁用状态
- 基本验证和限制
- 事件处理基础
- ViewChild 组件访问
时间配置
📄 阅读: references/time-configuration.md
- 自定义时间格式(format 属性)
- TimeFormatObject 和骨架选项
- 步长间隔和时间粒度
- 最小/最大时间限制
- 用于时间滚动的 ScrollTo 位置
- 弹出列表配置
事件和回调
📄 阅读: references/events-and-callbacks.md
- 搭配 ChangeEventArgs 使用的 Change 事件
- 焦点/失焦事件处理
- 打开/关闭弹出框事件
- created/destroyed 生命周期事件
- 使用清除按钮时触发的 cleared 事件
- 用于自定义时间格式的 ItemRender
方法和命令式访问
📄 阅读: references/methods-and-imperative-access.md
- ViewChild 访问和组件引用
- 使用 show() 打开时间弹出框
- 使用 hide() 关闭时间弹出框
- 使用 focusIn/focusOut 管理焦点
- 使用 getPersistData() 持久化状态
高级功能
📄 阅读: references/advanced-features.md
- 带掩码占位符的掩码输入模式
- 跨页面重新加载保存状态
- RTL(从右到左)语言支持
- 浮动标签类型和行为
- 严格模式验证和错误状态
- 键盘快捷键和按键配置
- 时区偏移处理
- 移动设备的全屏模式
- 清除按钮的显示和行为
- OpenOnFocus 弹出框触发方式
样式和自定义
📄 阅读: references/styling-and-customization.md
- CSS 类自定义(cssClass 属性)
- 主题选择和切换
- 深色模式实现
- 组件宽度和 z-index 配置
- HTML 属性注入(htmlAttributes)
- 占位符和启用状态样式
- 禁用日期的样式和外观
无障碍与全球化
📄 阅读: references/accessibility-and-globalization.md
- 符合 WCAG 2.2 和 Section 508 标准
- WAI-ARIA 属性和角色
- 键盘导航(方向键、回车、空格、退出)
- 兼容屏幕阅读器并提供播报
- 本地化和 locale 属性用法
- 时间格式差异
- 支持 RTL 文本方向
API 参考
📄 阅读: references/api-reference.md
- 完整的属性参考,包括类型和默认值
- 所有方法签名及其参数和返回类型
- 所有事件及其事件参数类型
- 属性说明和使用场景
- 方法示例和常见模式
- 类型接口和枚举
- 键盘快捷键的关键配置
- 全面的逐属性指南
快速入门示例
// app.component.ts
import { Component } from '@angular/core';
import { ChangeEventArgs } from '@syncfusion/ej2-calendars';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Simple time value
timeValue: Date = new Date();
// Configuration
minTime: Date = new Date(2026, 2, 24, 8, 0); // 8:00 AM
maxTime: Date = new Date(2026, 2, 24, 20, 0); // 8:00 PM
format: string = 'hh:mm a';
step: number = 30; // 30-minute intervals
// Event handler
onTimeChange(args: ChangeEventArgs): void {
console.log('Selected Time:', args.value);
console.log('Selected Text:', args.text);
console.log('Is User Interaction:', args.isInteracted);
}
onPopupOpen(): void {
console.log('Time popup opened');
}
onPopupClose(): void {
console.log('Time popup closed');
}
}
<div style="padding: 20px;">
<h2>Select a Time</h2>
<ejs-timepicker
id="timepicker"
[value]="timeValue"
[format]="format"
[min]="minTime"
[max]="maxTime"
[step]="step"
placeholder="Select time"
(change)="onTimeChange($event)"
(open)="onPopupOpen()"
(close)="onPopupClose()">
</ejs-timepicker>
<p *ngIf="timeValue">
Selected Time: {{ timeValue | date:'shortTime' }}
</p>
</div>
常见模式
模式 1:选择营业时间
选择营业时间内的时间(上午 9 点至下午 6 点):
export class AppComponent {
minTime: Date = new Date(2026, 2, 24, 9, 0); // 9:00 AM
maxTime: Date = new Date(2026, 2, 24, 18, 0); // 6:00 PM
timeValue: Date = new Date(2026, 2, 24, 10, 0);
format: string = 'hh:mm a';
step: number = 15; // 15-minute intervals
}
<ejs-timepicker
[value]="timeValue"
[min]="minTime"
[max]="maxTime"
[step]="step"
[format]="format"
placeholder="Select appointment time">
</ejs-timepicker>
模式 2:24 小时制
以 24 小时制显示时间:
export class AppComponent {
timeValue: Date = new Date();
format: string = 'HH:mm'; // 24-hour format
step: number = 30;
}
<ejs-timepicker
[value]="timeValue"
[format]="format"
[step]="step"
placeholder="Select time (24-hour)">
</ejs-timepicker>
模式 3:使用掩码输入引导填写
使用掩码输入引导用户填写时间:
export class AppComponent {
timeValue: Date;
enableMask: boolean = true;
maskPlaceholder = {
hour: 'hh',
minute: 'mm',
second: 'ss'
};
format: string = 'hh:mm:ss a';
}
<ejs-timepicker
[value]="timeValue"
[enableMask]="enableMask"
[maskPlaceholder]="maskPlaceholder"
format="hh:mm:ss a">
</ejs-timepicker>
模式 4:集成响应式表单
将 timepicker 集成到 Angular 响应式表单中:
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
export class AppComponent {
appointmentForm: FormGroup;
constructor(private fb: FormBuilder) {
this.appointmentForm = this.fb.group({
appointmentTime: [
new Date(),
[Validators.required]
]
});
}
submitForm(): void {
if (this.appointmentForm.valid) {
console.log(this.appointmentForm.value);
}
}
}
<form [formGroup]="appointmentForm">
<ejs-timepicker
formControlName="appointmentTime"
format="hh:mm a"
placeholder="Select time">
</ejs-timepicker>
<button (click)="submitForm()" [disabled]="!appointmentForm.valid">
Submit
</button>
</form>
模式 5:选择时间范围
选择一段时长的开始和结束时间:
export class AppComponent {
startTime: Date = new Date();
endTime: Date = new Date(Date.now() + 3600000); // +1 hour
onStartTimeChange(args: ChangeEventArgs): void {
// Ensure end time is after start time
if (args.value && this.endTime <= args.value) {
this.endTime = new Date(args.value.getTime() + 3600000); // +1 hour
}
}
}
<div>
<label>Start Time:</label>
<ejs-timepicker
[value]="startTime"
format="hh:mm a"
(change)="onStartTimeChange($event)">
</ejs-timepicker>
<label>End Time:</label>
<ejs-timepicker
[value]="endTime"
[min]="startTime"
format="hh:mm a">
</ejs-timepicker>
</div>
关键属性参考
| 属性 | 类型 | 用途 |
|---|---|---|
value | Date | 用于双向绑定的选定时间值 |
format | string | 时间显示格式(例如,'hh:mm a') |
min | Date | 可选时间下限 |
max | Date | 可选时间上限 |
step | number | 时间间隔(分钟)(15、30、60) |
enabled | boolean | 启用或禁用组件 |
readonly | boolean | 将输入设为只读(仅可从弹出窗口选择) |
placeholder | string | 输入框中的占位文本 |
enableMask | boolean | 启用掩码输入模式 |
strictMode | boolean | 仅允许有效值 |
enableRtl | boolean | 支持从右向左书写的语言 |
enablePersistence | boolean | 在页面重新加载后保留值 |
scrollTo | Date | 时间列表中的默认滚动位置 |
locale | string | 格式化所用的区域设置(例如,'en-US'、'de-DE') |
cssClass | string | 用于设置样式的自定义 CSS 类 |
width | string | 组件宽度 |
zIndex | number | 弹出窗口的 Z-index |
showClearButton | boolean | 显示或隐藏清除图标 |
openOnFocus | boolean | 输入框获得焦点时打开弹出窗口 |
floatLabelType | string | 浮动标签行为(Never/Always/Auto) |
常见使用场景
预约系统
- 从列表中选择可用时间段
- 通过最小/最大时间限制营业时间
- 使用 15 或 30 分钟的步长间隔
- 使用必填验证器处理表单验证
- 显示所选时间的确认信息
排班管理
- 选择班次的开始和结束时间
- 应用班次时间限制
- 支持多个时区偏移量
- 处理跨午夜的班次转换
- 以 ISO 格式导出时间
会议安排
- 在营业时间限制内选择会议时间
- 使用 30 分钟的步长间隔设置标准时长
- 按用户的区域设置格式显示时间
- 通过验证防止重复预订
- 与日历组件同步以检查可用时间
时间跟踪
- 记录上班打卡和下班打卡时间
- 限制在营业时间内
- 使用掩码输入快速填写
- 保留时间记录以供审计
- 导出时间以便与薪资系统集成
活动报名
- 选择活动参与时间段
- 显示可用时间范围
- 使用清除按钮进行更正
- 支持多种时间格式
- 为辅助技术提供无障碍支持
后续步骤
- 从入门指南开始 → 安装并配置组件
- 构建基础实现 → 创建简单的时间选择器
- 添加事件处理 → 响应用户交互
- 实现高级功能 → 添加带掩码的输入、持久化和 RTL 支持
- 自定义外观 → 应用主题和自定义样式
- 确保无障碍访问 → 支持键盘和屏幕阅读器
- 参考 API → 根据需要查阅完整的 API 文档