
Syncfusion Blazor Calendars
- 236 installs
- 4 repo stars
- Updated July 28, 2026
- syncfusion/blazor-ui-components-skills
Use syncfusion-blazor-calendars for development tasks
About
syncfusion-blazor-calendars: A skill for development. This provides functionality for development workflows.
- syncfusion-blazor-calendars
Syncfusion Blazor Calendars by the numbers
- 236 all-time installs (skills.sh)
- +14 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,668 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/blazor-ui-components-skills --skill syncfusion-blazor-calendarsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 236 |
|---|---|
| repo stars | ★ 4 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/blazor-ui-components-skills ↗ |
What it does
Use syncfusion-blazor-calendars for development tasks
Files
Implementing Syncfusion Blazor Calendars
Calendar
The Calendar component is a lightweight, feature-rich date selection component that provides flexible date picking, multiple views (month/year/decade), date range constraints, localization, and accessibility compliance. Use this skill whenever you need to implement date selection, calendar display, or date-based UI interactions.
When to Use This Skill
Use this skill when:
- Building date pickers, calendar widgets, or date selection interfaces
- Adding date range constraints (Min/Max dates)
- Implementing multi-month or drill-down date selection (Year/Decade views)
- Handling date value changes and events
- Styling calendars or customizing appearance
- Supporting international date formats and RTL layouts
- Creating accessible calendar interfaces with keyboard navigation
Related components:
- DatePicker (date input with calendar dropdown)
- DateRangePicker (date range selection)
- DateTimePicker (date + time selection)
- Scheduler (complex date-based scheduling)
Component Overview
| Feature | Details |
|---|---|
| Views | Month (default), Year, Decade - hierarchical drill-down navigation |
| Selection | Single date, date ranges (Min/Max), multi-select |
| Data Types | DateTime, DateTime?, DateOnly (.NET 6+) |
| Binding | One-way, two-way (@bind-Value), dynamic |
| Events | ValueChange, OnRenderDayCell, Created, Destroyed, Navigated |
| Localization | Multi-language, RTL support, locale customization |
| Accessibility | WCAG 2.2 AA, keyboard navigation, screen reader support |
| Styling | CSS customization, theme integration, special date highlights |
Documentation & Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation & NuGet packages
- Web & Server app setup
- Blazor namespaces & service registration
- Basic calendar implementation
- Min/Max date constraints
Calendar Views & Navigation
📄 Read: references/calendar-views.md
- Month, Year, Decade views
- Start & Depth properties
- View restrictions & drill-down navigation
- Restricting date selection depth
Date Selection & Data Binding
📄 Read: references/date-selection-binding.md
- Value property & date binding
- One-way vs two-way binding (
@bind-Value) - DateOnly support (.NET 6+)
- Dynamic value changes
- Date range constraints
Events & Interactions
📄 Read: references/events-handling.md
- ValueChange event (date selection)
- Selected/DeSelected events (multi-selection)
- OnRenderDayCell event (custom rendering)
- Created & Destroyed lifecycle events
- Navigated event (view changes)
- Event args & reactive patterns
- Using CalendarEvents child component
Styling & Customization
📄 Read: references/styling-appearance.md
- CSS customization patterns
- Background colors, borders, hover states
- Day cell styling
- Header & title customization
- Today button & selected date styling
- Special date highlighting
Localization & Globalization
📄 Read: references/localization-globalization.md
- Locale support & language files
- Right-to-Left (RTL) layouts
- Islamic calendar & custom calendars
- Week customization (first day of week)
- Date format localization
Accessibility & Keyboard Navigation
📄 Read: references/accessibility.md
- WCAG 2.2 AA compliance
- Screen reader support (WAI-ARIA)
- Keyboard navigation shortcuts
- Focus management & ARIA attributes
Advanced Features & Patterns
📄 Read: references/advanced-features.md
- Show/hide other month dates
- Custom cell rendering patterns
- Multiple date selection
- Week number display
- Performance optimization
- Common integration patterns
Quick Start Example
@using Syncfusion.Blazor.Calendars
<!-- Basic Calendar -->
<SfCalendar TValue="DateTime?" Value="@SelectedDate"></SfCalendar>
<!-- Calendar with Date Range -->
<SfCalendar TValue="DateTime?"
Value="@SelectedDate"
Min="@MinDate"
Max="@MaxDate">
</SfCalendar>
<!-- Calendar with Value Change Event -->
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate">
<CalendarEvents TValue="DateTime?" ValueChange="@OnDateChanged"></CalendarEvents>
</SfCalendar>
<!-- Multi-Selection Calendar -->
<SfCalendar TValue="DateTime?"
IsMultiSelection="true"
@bind-Values="@SelectedDates">
<CalendarEvents TValue="DateTime?"
Selected="@OnDateSelected"
DeSelected="@OnDateDeselected">
</CalendarEvents>
</SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
public DateTime[] SelectedDates { get; set; } = new DateTime[] { };
private void OnDateChanged(ChangedEventArgs<DateTime?> args)
{
SelectedDate = args.Value;
// Handle date change
}
private void OnDateSelected(SelectedEventArgs<DateTime?> args)
{
// Handle date added to selection
}
private void OnDateDeselected(DeSelectedEventArgs<DateTime?> args)
{
// Handle date removed from selection
}
}Common Patterns
Pattern 1: Date Range Selection
Define Min and Max boundaries to constrain user selection:
<SfCalendar TValue="DateTime?" Value="@SelectedDate"
Min="@MinDate" Max="@MaxDate"></SfCalendar>Pattern 2: Two-Way Data Binding
Keep Calendar in sync with component state:
<p>Selected: @SelectedDate</p>
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate"></SfCalendar>Pattern 3: Custom Cell Rendering
Highlight or customize specific date cells during render:
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@CustomizeCell"></CalendarEvents>
</SfCalendar>Pattern 4: View Restrictions
Limit navigation to specific view levels (e.g., Year → Month only):
<SfCalendar TValue="DateTime?"
Start="CalendarView.Year"
Depth="CalendarView.Month"></SfCalendar>Pattern 5: Localization
Render calendar in specific language/culture:
<SfCalendar TValue="DateTime?" EnableRtl="false"></SfCalendar>Key Props & When to Use
| Property | Type | Purpose | Example |
|---|---|---|---|
Value | TValue | Selected date (one-way binding) | Value="@SelectedDate" |
@bind-Value | TValue | Two-way data binding | @bind-Value="@SelectedDate" |
Values | DateTime[] | Multiple selected dates (multi-select mode) | Values="@SelectedDates" |
@bind-Values | DateTime[] | Two-way binding for multi-selection | @bind-Values="@SelectedDates" |
IsMultiSelection | bool | Enable multiple date selection | IsMultiSelection="true" |
Min | DateTime | Earliest selectable date (inclusive) | Min="@minSelectableDate" |
Max | DateTime | Latest selectable date (inclusive) | Max="@maxSelectableDate" |
Start | CalendarView | Initial view (Month/Year/Decade) | Start="CalendarView.Year" |
Depth | CalendarView | Deepest view level for drilling | Depth="CalendarView.Month" |
ShowTodayButton | bool | Display "Today" button in footer | ShowTodayButton="true" |
CalendarMode | CalendarType | Calendar system (Gregorian/Islamic) | CalendarMode="CalendarType.Islamic" |
WeekRule | CalendarWeekRule | Week numbering calculation rule | WeekRule="CalendarWeekRule.FirstDay" |
DayHeaderFormat | DayHeaderFormats | Day header display format | DayHeaderFormat="DayHeaderFormats.Short" |
EnableRtl | bool | Right-to-left layout | EnableRtl="true" |
WeekNumber | bool | Display week numbers in calendar | WeekNumber="true" |
FirstDayOfWeek | int | First day (0=Sunday, 1=Monday) | FirstDayOfWeek="1" |
CssClass | string | Custom CSS class for styling | CssClass="custom-calendar" |
Enabled | bool | Enable/disable component | Enabled="false" |
Common Use Cases
1. Appointment Booking: Calendar with date range (available days) + event handling 2. Date Filter: Multi-view calendar for drilling down to specific date 3. Deadline Selection: Min/Max constraints to valid date ranges 4. Report Viewing: Year/Month view for period selection 5. International App: RTL + locale support for multi-language UIs 6. Accessible Forms: Keyboard-navigable date input with screen reader support
Working with Events
All calendar components use child event components to declare event handlers. This approach provides type safety and clear separation of concerns.
Event Child Components
- Calendar: Use
<CalendarEvents>child component - DatePicker: Use
<DatePickerEvents>child component - DateRangePicker: Use
<DateRangePickerEvents>child component - DateTimePicker: Use
<DateTimePickerEvents>child component - TimePicker: Use
<TimePickerEvents>child component
Example: Calendar with Events
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate">
<CalendarEvents TValue="DateTime?"
ValueChange="@OnValueChanged"
OnRenderDayCell="@OnDayCellRender"
Navigated="@OnNavigated">
</CalendarEvents>
</SfCalendar>
@code {
private DateTime? SelectedDate { get; set; }
private void OnValueChanged(ChangedEventArgs<DateTime?> args)
{
Console.WriteLine($"Date changed: {args.Value}");
}
private void OnDayCellRender(RenderDayCellEventArgs args)
{
// Disable weekends
if (args.Date.DayOfWeek == DayOfWeek.Saturday || args.Date.DayOfWeek == DayOfWeek.Sunday)
{
args.IsDisabled = true;
}
}
private void OnNavigated(NavigatedEventArgs args)
{
Console.WriteLine($"Navigated to: {args.View}");
}
}Common Event Patterns
Pattern 1: Value Change with Validation
<SfDatePicker TValue="DateTime?" @bind-Value="@OrderDate">
<DatePickerEvents TValue="DateTime?" ValueChange="@ValidateAndUpdate"></DatePickerEvents>
</SfDatePicker>
@code {
private DateTime? OrderDate { get; set; }
private void ValidateAndUpdate(ChangedEventArgs<DateTime?> args)
{
if (args.Value.HasValue && args.Value.Value > DateTime.Now.AddMonths(6))
{
// Show error - date too far in future
OrderDate = DateTime.Now;
}
else
{
OrderDate = args.Value;
}
}
}Pattern 2: Popup Lifecycle Management
<SfDateTimePicker TValue="DateTime?" @bind-Value="@AppointmentTime">
<DateTimePickerEvents TValue="DateTime?"
OnOpen="@HandlePopupOpen"
OnClose="@HandlePopupClose">
</DateTimePickerEvents>
</SfDateTimePicker>
@code {
private DateTime? AppointmentTime { get; set; }
private void HandlePopupOpen(PopupObjectArgs args)
{
Console.WriteLine("Popup opened");
// Can cancel opening: args.Cancel = true;
}
private void HandlePopupClose(PopupObjectArgs args)
{
Console.WriteLine("Popup closed");
}
}Pattern 3: Custom Cell Rendering
<SfCalendar TValue="DateTime?" @bind-Value="@EventDate">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@CustomizeCells"></CalendarEvents>
</SfCalendar>
@code {
private DateTime? EventDate { get; set; }
private List<DateTime> EventDates = new List<DateTime>
{
DateTime.Now.AddDays(5),
DateTime.Now.AddDays(10)
};
private void CustomizeCells(RenderDayCellEventArgs args)
{
// Highlight event dates
if (EventDates.Any(d => d.Date == args.Date.Date))
{
args.CellData.ClassList = "e-special-date";
}
}
}Event Argument Types Reference
IMPORTANT: Different components use different event argument types for the ValueChange event:
| Component | ValueChange Event Argument Type | Notes |
|---|---|---|
| Calendar | ChangedEventArgs<TValue> | For single and multi-date selection |
| DatePicker | ChangedEventArgs<TValue> | Includes Value, IsInteracted, Event properties |
| DateTimePicker | ChangedEventArgs<TValue> | Same as DatePicker |
| TimePicker | ChangeEventArgs<TValue> | Note: Different class name (no 'd') |
| DateRangePicker | RangePickerEventArgs<TValue> | Includes StartDate and EndDate properties |
Key Differences:
ChangedEventArgs<TValue>(with 'd') - Used by Calendar, DatePicker, DateTimePicker- Properties:
Value,Values(for multi-selection),IsInteracted,Event,Element,Name ChangeEventArgs<TValue>(no 'd') - Used by TimePicker only- Properties:
Value,Text,IsInteracted,Event,Element RangePickerEventArgs<TValue>- Used by DateRangePicker only- Properties:
StartDate,EndDate,Text,Value,IsInteracted,Event,Element
---
DatePicker
A comprehensive skill for implementing and customizing the DatePicker component. This skill helps you install, configure, and integrate DatePicker across Blazor Server, Blazor WebAssembly, and Blazor Web App projects.
When to Use This Skill
Use this skill when you need to:
- Install and set up Syncfusion DatePicker in any Blazor project type
- Implement basic date selection with input validation
- Configure one-way and two-way data binding
- Set custom date formats and input formats
- Apply date range constraints (min/max dates)
- Highlight or disable special dates
- Handle DatePicker events (ValueChange, OnClose, Focus, Blur)
- Globalize and localize the component (different languages/calendars)
- Support Islamic Calendar or other calendar systems
- Use DateOnly (.NET 6+) with DatePicker
- Style and customize appearance (readonly, disabled states, themes)
- Implement keyboard navigation and accessibility
- Troubleshoot data binding, formatting, or event issues
- Optimize performance in Blazor Server vs WebAssembly
- Integrate date selection with forms and APIs
Component Overview
The DatePicker component provides an intuitive calendar UI for users to select single dates. It supports:
- Multiple Input Methods: Direct typing, calendar picker, or both
- Date Constraints: Min/max date ranges, disabled dates, special highlights
- Flexible Formatting: Custom display formats and input formats
- Global Support: Multiple languages, calendars (Gregorian, Islamic), RTL
- Accessibility: WCAG compliance, keyboard navigation, screen reader support
- Event System: Value changes, popup open/close, focus/blur events
- Theme Support: Bootstrap, Material, Fluent, Tailwind CSS
Installation Quick Start
1. Install NuGet Package
dotnet add package Syncfusion.Blazor.Calendars
dotnet add package Syncfusion.Blazor.Themes2. Import in _Imports.razor
@using Syncfusion.Blazor
@using Syncfusion.Blazor.Calendars3. Register in Program.cs
builder.Services.AddSyncfusionBlazor();4. Add Theme in App.razor or Layout
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js"></script>5. Use in Component
<SfDatePicker TValue="DateTime?" @bind-Value="@selectedDate">
<DatePickerEvents TValue="DateTime?" ValueChange="@OnDateChange"></DatePickerEvents>
</SfDatePicker>
@code {
DateTime? selectedDate = new DateTime(2026, 3, 18);
void OnDateChange(ChangedEventArgs<DateTime?> args)
{
selectedDate = args.Value;
}
}Documentation Navigation Guide
Choose a reference based on your task:
Getting Started
📄 Read: references/getting-started.md
- Installation in Blazor Server, WebAssembly, and Web App
- NuGet package setup
- Theme configuration
- Service registration
- Basic DatePicker example
Data Binding
📄 Read: references/data-binding.md
- One-way binding with
Valueproperty - Two-way binding with
@bind-Value - Dynamic value updates and null handling
- Binding to DateTime vs DateTime?
Date Formats & Input
📄 Read: references/date-formats-and-input.md
- Display format customization (d/M/yyyy, dd/MM/yyyy, etc.)
- Input format patterns
- Placeholder text configuration
- Format parsing and validation
- Custom format examples
Date Range & Constraints
📄 Read: references/date-range-and-constraints.md
- Min/Max date restrictions
- Disabled specific dates
- Special date highlighting
- Date validation logic
- Preventing invalid selections
Events & Interaction
📄 Read: references/events.md
- ValueChange event handling
- OnOpen/OnClose events (popup lifecycle)
- Selected event (date selection in calendar)
- Focus/Blur events
- Cleared event (clear button clicked)
- Created/Destroyed lifecycle events
- Navigated event (calendar view navigation)
- OnRenderDayCell event (custom day cell rendering)
- Using DatePickerEvents child component
Advanced Features
📄 Read: references/advanced-features.md
- Islamic Calendar support
- DateOnly (.NET 6+) support
- Globalization and localization
- Week number display
- Different view modes
- Mask support and input masking
Styling & Appearance
📄 Read: references/styling-and-appearance.md
- CSS customization and themes
- Readonly state styling
- Disabled state styling
- RTL (right-to-left) support
- Theme switching (Bootstrap, Material, Fluent, Tailwind)
- Custom styling examples
Accessibility
📄 Read: references/accessibility.md
- WCAG 2.1 compliance
- Keyboard navigation (arrow keys, Enter, Escape)
- ARIA attributes and roles
- Screen reader support
- Color contrast and visual indicators
- Focus management
Server vs WebAssembly
📄 Read: references/server-vs-webassembly.md
- Blazor Server vs WebAssembly differences
- Blazor Web App (.NET 8+) setup
- Render modes (InteractiveServer, InteractiveWebAssembly)
- Performance considerations
- Event interactivity
Troubleshooting
📄 Read: references/troubleshooting.md
- Data binding issues
- Date format problems
- Event handling problems
- Styling and layout issues
- Performance optimization
- Common error messages and solutions
Common Patterns
Pattern 1: Basic Date Selection
<SfDatePicker TValue="DateTime?" Value="@selectedDate"
Placeholder="Select a date"></SfDatePicker>Use when: User needs a simple, standard date picker for form input.
Pattern 2: Date Range with Constraints
<SfDatePicker TValue="DateTime?" Value="@selectedDate"
Min="@minDate" Max="@maxDate"></SfDatePicker>Use when: Date must fall within a specific range (e.g., future dates only, event dates).
Pattern 3: Two-Way Binding
<SfDatePicker TValue="DateTime?" @bind-Value="@formData.BirthDate"></SfDatePicker>Use when: DatePicker must automatically update parent component state or form data.
Pattern 4: Event-Driven Logic
<SfDatePicker TValue="DateTime?">
<DatePickerEvents TValue="DateTime?" ValueChange="@OnDateSelected"></DatePickerEvents>
</SfDatePicker>
@code {
void OnDateSelected(ChangedEventArgs<DateTime?> args)
{
// Trigger calculations, API calls, or validation
}
}Use when: Selection should trigger workflows, calculations, or dependent updates.
Pattern 5: Formatted Display with Custom Input
<SfDatePicker TValue="DateTime?" Value="@selectedDate"
Format="dd/MM/yyyy" Placeholder="DD/MM/YYYY"></SfDatePicker>Use when: Date display must match regional or business requirements.
Key Properties
| Property | Type | Purpose |
|---|---|---|
Value | TValue | The selected date (one-way binding) |
@bind-Value | TValue | Two-way data binding |
Min | DateTime | Earliest selectable date |
Max | DateTime | Latest selectable date |
Format | string | Display format pattern (e.g., "dd/MM/yyyy") |
Placeholder | string | Input placeholder text |
AllowEdit | bool | Allow manual text input editing |
StrictMode | bool | Restrict to valid dates only |
EnableMask | bool | Enable input masking for date entry |
OpenOnFocus | bool | Open calendar popup when input is focused |
FloatLabelType | FloatLabelType | Float label behavior (Auto/Always/Never) |
InputFormats | string[] | Array of acceptable input formats |
Enabled | bool | Enable/disable component |
Readonly | bool | Read-only mode (no user input) |
ShowClearButton | bool | Show clear button to reset value |
WeekNumber | bool | Display week numbers in calendar |
Start | CalendarView | Initial calendar view (Month/Year/Decade) |
Depth | CalendarView | Deepest view level allowed |
ZIndex | int | Z-index for popup positioning |
Width | string | Component width (e.g., "300px") |
CssClass | string | Custom CSS class for styling |
Performance Tips
1. Use DateTime? (nullable) for optional date fields—avoids default date confusion 2. Lazy-load DatePicker in modals or expandable sections—reduces initial render cost 3. Minimize format conversions in event handlers—cache formatted strings when possible 4. Use InteractiveWebAssembly for date-heavy UIs—offloads processing to client 5. Batch value updates in loops—avoid rapid re-renders with multiple ValueChange triggers
---
DateRangePicker
A comprehensive skill for implementing and customizing the DateRangePicker component. This component enables users to select date ranges with calendar pickers, providing features for range constraints, customization, accessibility, and globalization.
When to Use This Skill
Use this skill when you need to:
- Install and set up the DateRangePicker component in Blazor applications
- Create date range selection interfaces
- Set minimum and maximum date constraints
- Bind component values to data models
- Customize placeholder text, first day of week, and visual appearance
- Implement keyboard navigation and accessibility features
- Handle component events (change, blur, focus, etc.)
- Configure globalization and localization for different cultures
- Support DateOnly type for .NET 6+ projects
- Open popups on input click or programmatically
- Display week numbers in the calendar
- Apply custom CSS styling and theming
- Work with RTL (right-to-left) languages
- Debug common DateRangePicker issues
Component Overview
SfDateRangePicker is a calendar-based input component that allows users to select a continuous date range. Key characteristics:
- Dual Calendar View: Shows two calendar months for easy range selection
- Range Constraints: Min/Max properties enforce date restrictions
- Flexible Data Binding: Works with DateTime, DateTime?, and DateOnly types
- Customizable: First day of week, placeholder, popup behavior, styling
- Accessible: Full WCAG 2.2 AA compliance with keyboard navigation
- Globalized: Supports multiple cultures, RTL, and date formatting
- Event-Driven: Comprehensive event system for user interactions
- Mobile-Friendly: Touch-optimized calendar interface
Documentation and Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation via NuGet packages
- Namespace imports and service registration
- Basic component setup (WebAssembly and Server apps)
- Adding theme stylesheet
- Setting Min/Max date constraints
- Rendering your first DateRangePicker
Range Selection & Data Binding
📄 Read: references/range-selection.md
- Single vs range date selection modes
- Two-way data binding with @bind
- Programmatic range updates
- Clearing date selections
- Using DateOnly type for .NET 6+
- Value change handling
Customization & Styling
📄 Read: references/customization-and-styling.md
- Configuring first day of week
- Setting placeholder text
- Custom CSS class application
- Opening popup on input click
- Displaying week numbers
- Appearance and visual customization
- Theme integration
Data & Globalization
📄 Read: references/data-and-globalization.md
- Data binding patterns and best practices
- DateOnly type support and usage
- Globalization configuration
- Culture-specific date formatting
- Right-to-left (RTL) language support
- Localization for international audiences
Events & Interactions
📄 Read: references/events-and-interactions.md
- ValueChange event (range selection complete)
- RangeSelected event (individual date selections)
- OnOpen/OnClose events (popup lifecycle)
- Focus/Blur events
- Cleared event (clear button clicked)
- Created/Destroyed lifecycle events
- Navigated event (calendar view navigation)
- OnRenderDayCell event (custom day cell rendering)
- Using DateRangePickerEvents child component
- Event argument types (RangePickerEventArgs<TValue>)
Accessibility
📄 Read: references/accessibility.md
- WCAG 2.2 AA compliance overview
- Keyboard navigation shortcuts
- Calendar month navigation keys
- ARIA attributes and screen reader support
- Mobile device accessibility features
- Testing and validating accessibility
Quick Start
Basic DateRangePicker
@using Syncfusion.Blazor.Calendars
<SfDateRangePicker TValue="DateTime?" Placeholder="Select a date range"></SfDateRangePicker>With Date Constraints
<SfDateRangePicker TValue="DateTime?"
Placeholder="Choose a range"
Min="@MinDate"
Max="@MaxDate">
</SfDateRangePicker>
@code {
public DateTime MinDate { get; set; } = new DateTime(2024, 1, 1);
public DateTime MaxDate { get; set; } = new DateTime(2024, 12, 31);
}With Data Binding (StartDate/EndDate)
<SfDateRangePicker TValue="DateTime?"
@bind-StartDate="StartDate"
@bind-EndDate="EndDate">
</SfDateRangePicker>
@code {
private DateTime? StartDate { get; set; }
private DateTime? EndDate { get; set; }
}With Range Constraints
<SfDateRangePicker TValue="DateTime?"
MinDays="3"
MaxDays="30"
@bind-StartDate="StartDate"
@bind-EndDate="EndDate">
</SfDateRangePicker>
@code {
// User must select range between 3 and 30 days
private DateTime? StartDate { get; set; }
private DateTime? EndDate { get; set; }
}With Preset Ranges
<SfDateRangePicker TValue="DateTime?">
<DateRangePickerPresets>
<DateRangePickerPreset Label="Last 7 Days" Start="@last7DaysStart" End="@currentDate"></DateRangePickerPreset>
<DateRangePickerPreset Label="Last 30 Days" Start="@last30DaysStart" End="@currentDate"></DateRangePickerPreset>
<DateRangePickerPreset Label="This Month" Start="@currentMonthStart" End="@currentDate"></DateRangePickerPreset>
</DateRangePickerPresets>
</SfDateRangePicker>
@code {
private DateTime currentDate = DateTime.Now;
private DateTime last7DaysStart = DateTime.Now.AddDays(-7);
private DateTime last30DaysStart = DateTime.Now.AddDays(-30);
private DateTime currentMonthStart = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
}Key Properties
| Property | Type | Purpose |
|---|---|---|
StartDate | TValue | Start date of the range (one-way binding) |
@bind-StartDate | TValue | Two-way binding for start date |
EndDate | TValue | End date of the range (one-way binding) |
@bind-EndDate | TValue | Two-way binding for end date |
Value | Object | Combined range value (legacy) |
Min | DateTime | Earliest selectable date |
Max | DateTime | Latest selectable date |
MinDays | int? | Minimum required days in range |
MaxDays | int? | Maximum allowed days in range |
Presets | List<Presets> | Predefined date range presets |
Separator | string | Separator between start and end dates (default: "-") |
Format | string | Display format pattern |
Placeholder | string | Input placeholder text |
AllowEdit | bool | Allow manual text input editing |
StrictMode | bool | Restrict to valid dates only |
OpenOnFocus | bool | Open popup when input is focused |
FloatLabelType | FloatLabelType | Float label behavior |
Enabled | bool | Enable/disable component |
Readonly | bool | Read-only mode |
ShowClearButton | bool | Show clear button |
WeekNumber | bool | Display week numbers |
FirstDayOfWeek | int | First day (0=Sunday, 1=Monday) |
ZIndex | int | Z-index for popup |
Width | string | Component width |
CssClass | string | Custom CSS class |
Common Patterns
Pattern 1: Range Selection with Validation
<SfDateRangePicker TValue="DateTime?"
@bind-Value="BookingRange"
Min="@minBookingDate"
Placeholder="Select booking dates">
</SfDateRangePicker>
@code {
private DateTime? BookingRange { get; set; }
private DateTime minBookingDate = DateTime.Today;
}Pattern 2: Event Handling
<SfDateRangePicker TValue="DateTime?"
@bind-StartDate="@StartDate"
@bind-EndDate="@EndDate">
<DateRangePickerEvents TValue="DateTime?" ValueChange="@OnDateRangeChange"></DateRangePickerEvents>
</SfDateRangePicker>
@code {
private DateTime? StartDate { get; set; }
private DateTime? EndDate { get; set; }
private void OnDateRangeChange(RangePickerEventArgs<DateTime?> args)
{
// Handle date range selection
Console.WriteLine($"Start: {args.StartDate}, End: {args.EndDate}");
}
}Pattern 3: Multiple Instances with Different Constraints
<div>
<h4>Q1 Reporting Period (Jan-Mar)</h4>
<SfDateRangePicker TValue="DateTime?"
Min="@new DateTime(2024, 1, 1)"
Max="@new DateTime(2024, 3, 31)"
Placeholder="Select dates">
</SfDateRangePicker>
</div>
<div>
<h4>Q2 Reporting Period (Apr-Jun)</h4>
<SfDateRangePicker TValue="DateTime?"
Min="@new DateTime(2024, 4, 1)"
Max="@new DateTime(2024, 6, 30)"
Placeholder="Select dates">
</SfDateRangePicker>
</div>---
DateTimePicker
A comprehensive guide for implementing and customizing the DateTimePicker component. The DateTimePicker enables users to select both date and time values with support for multiple formats, masks, globalization, and extensive customization options.
When to Use This Skill
Use this skill when you need to:
- Install and set up the DateTimePicker component in a Blazor application
- Implement date and time selection functionality
- Format date/time values using custom format strings
- Apply input masks and validate user input
- Handle DateTimePicker events (ValueChange, OnOpen, OnClose, etc.)
- Bind the component to data models
- Set minimum and maximum date/time constraints
- Highlight special dates or disable specific dates
- Implement globalization (RTL, multiple locales)
- Support Islamic calendar or other calendar systems
- Customize component appearance and styling
- Configure placeholder text and input validation
- Enable strict mode for input validation
- Display week numbers in the calendar
Documentation
Getting Started
📄 Read: references/getting-started.md
- Installation and NuGet package setup
- Basic component initialization in Blazor Server/Web App
- Minimal working example
- Required imports and configurations
Date & Time Formatting
📄 Read: references/date-time-formatting.md
- Format string patterns and standard formats
- Custom date/time format configurations
- Locale-specific formatting
- Parse and display format handling
Data Binding & Events
📄 Read: references/data-binding-and-events.md
- Two-way binding for date/time values
- ValueChange event (date/time selection complete)
- OnOpen/OnClose events (popup lifecycle)
- Selected event (date selection in calendar)
- OnItemRender event (custom time list item rendering)
- Focus/Blur events
- Cleared event (clear button clicked)
- Created/Destroyed lifecycle events
- Navigated event (calendar view navigation)
- OnRenderDayCell event (custom day cell rendering)
- Using DateTimePickerEvents child component
- State management and data flow patterns
Date Ranges & Special Dates
📄 Read: references/date-ranges-and-special-dates.md
- Setting minimum and maximum date constraints
- Restricting date range selection
- Highlighting special dates
- Disabling specific dates or date ranges
- Week number configuration
Masking & Input Validation
📄 Read: references/masking-and-input-validation.md
- Input mask patterns for date/time entry
- Placeholder text configuration
- Input validation rules
- Strict mode enforcement and input behavior
- Validation edge cases
Customization & Styling
📄 Read: references/customization-and-styling.md
- CSS customization and class overrides
- Theme integration (Bootstrap, Material, Fluent, Tailwind)
- Component appearance and styling options
- Custom CSS properties and styling patterns
- Visual customization examples
Globalization & Accessibility
📄 Read: references/globalization-and-accessibility.md
- Globalization support (RTL, multiple locales)
- Islamic calendar implementation and configuration
- Accessibility features (WCAG compliance, keyboard navigation)
- ARIA attributes and screen reader support
- Internationalization best practices
Quick Start
Here's a minimal working example to get started with the DateTimePicker:
@page "/datetimepicker-demo"
@using Syncfusion.Blazor.Calendars
<div>
<label>Select Date and Time:</label>
<SfDateTimePicker TValue="DateTime?"
@bind-Value="@selectedDateTime"
Placeholder="Choose date and time">
<DateTimePickerEvents TValue="DateTime?" ValueChange="@OnValueChanged"></DateTimePickerEvents>
</SfDateTimePicker>
@if (selectedDateTime.HasValue)
{
<p>Selected: @selectedDateTime.Value.ToString("g")</p>
}
</div>
@code {
private DateTime? selectedDateTime;
private void OnValueChanged(ChangedEventArgs<DateTime?> args)
{
selectedDateTime = args.Value;
Console.WriteLine($"Date changed to: {selectedDateTime}");
}
}Common Patterns
Pattern 1: With Date Range Constraints
<SfDateTimePicker TValue="DateTime?"
Min="@minDate"
Max="@maxDate"
Value="selectedDateTime">
</SfDateTimePicker>
@code {
private DateTime minDate = new DateTime(2024, 1, 1);
private DateTime maxDate = new DateTime(2024, 12, 31);
private DateTime? selectedDateTime;
}Pattern 2: With Format Customization
<SfDateTimePicker TValue="DateTime?"
Format="dd/MM/yyyy HH:mm"
Value="selectedDateTime">
</SfDateTimePicker>Pattern 3: With Input Mask
<SfDateTimePicker TValue="DateTime?"
EnableMask="true"
Format="dd/MM/yyyy HH:mm"
Value="selectedDateTime">
<DateTimePickerMaskPlaceholder Day="dd" Month="MM" Year="yyyy" Hour="HH" Minute="mm"></DateTimePickerMaskPlaceholder>
</SfDateTimePicker>Pattern 4: With Data Binding
<SfDateTimePicker TValue="DateTime?"
@bind-Value="model.CreatedDate">
<DateTimePickerEvents TValue="DateTime?" ValueChange="@OnDateChanged"></DateTimePickerEvents>
</SfDateTimePicker>Key Properties
| Property | Type | Purpose |
|---|---|---|
Value | TValue | Gets or sets the selected date-time value |
@bind-Value | TValue | Two-way data binding |
Format | string | Display format (e.g., "dd/MM/yyyy HH:mm") |
TimeFormat | string | Format for time portion only (e.g., "HH:mm") |
Placeholder | string | Placeholder text for the input field |
Min | DateTime | Minimum selectable date (date portion) |
Max | DateTime | Maximum selectable date (date portion) |
MinTime | DateTime | Minimum selectable time |
MaxTime | DateTime | Maximum selectable time |
Step | int | Time interval step in minutes (default: 30) |
ScrollTo | DateTime? | Initial scroll position in time list |
AllowEdit | bool | Allows manual text input |
StrictMode | bool | Enforces strict input validation |
EnableMask | bool | Enable input masking for date/time entry |
OpenOnFocus | bool | Opens popup on input focus |
FloatLabelType | FloatLabelType | Float label behavior |
Enabled | bool | Enables/disables the component |
Readonly | bool | Makes the component read-only |
ShowClearButton | bool | Show clear button |
ShowTodayButton | bool | Displays today button in calendar |
WeekNumber | bool | Display week numbers |
FirstDayOfWeek | int | First day (0=Sunday, 1=Monday) |
Start | CalendarView | Initial calendar view |
Depth | CalendarView | Deepest view level |
ZIndex | int | Z-index for popup |
Width | string | Component width |
CssClass | string | Custom CSS class |
---
TimePicker
A comprehensive skill for implementing and customizing the TimePicker component. This skill covers installation, configuration, data binding, events, styling, accessibility, internationalization, and advanced features like input masking.
When to Use This Skill
Use this skill when you need to:
- Install and set up the TimePicker component in Blazor applications
- Create basic and advanced TimePicker implementations
- Configure time formats (12-hour, 24-hour, custom formats)
- Set up data binding (one-way, two-way, dynamic)
- Handle TimePicker events (ValueChange, OnOpen, OnClose, Blur, Focus, etc.)
- Customize appearance and styling with CSS
- Implement input masking and validation
- Configure accessibility (keyboard navigation, ARIA attributes, screen readers)
- Add globalization support (localization, RTL for Arabic/Hebrew)
- Set time intervals and step values
- Implement full-screen mode on mobile devices
Component Overview
The SfTimePicker is a Blazor input component for time selection. It provides:
- Popup time picker interface with scrollable time list
- Configurable time formats and intervals
- Two-way data binding support
- Built-in validation and masking
- Full accessibility compliance (WCAG 2.2, Section 508)
- RTL support for international audiences
- Mobile-responsive with full-screen mode
- Keyboard navigation shortcuts
Quick Start Example
Basic TimePicker
@using Syncfusion.Blazor.Calendars
<SfTimePicker TValue="DateTime?" Placeholder="Select a time"></SfTimePicker>TimePicker with Value Binding
@using Syncfusion.Blazor.Calendars
<p>Selected Time: @SelectedTime</p>
<SfTimePicker TValue="DateTime?" @bind-Value="@SelectedTime"></SfTimePicker>
@code {
public DateTime? SelectedTime { get; set; } = DateTime.Now;
}TimePicker with Format and Step
@using Syncfusion.Blazor.Calendars
<SfTimePicker TValue="DateTime?"
Value="@TimeValue"
Format="HH:mm"
Step=60
Placeholder="Select time (24-hour)">
</SfTimePicker>
@code {
public DateTime TimeValue { get; set; } = DateTime.Now;
}Key Props Reference
Key Properties
| Property | Type | Description | Default |
|---|---|---|---|
Value | TValue | Current time value (one-way binding) | null |
@bind-Value | TValue | Two-way data binding | - |
Placeholder | string | Placeholder text in input | "Select a time" |
Format | string | Display format string (HH:mm, hh:mm tt) | Culture-based |
InputFormats | string[] | Accepted input format patterns | Culture-based |
Step | int | Time interval in minutes | 30 |
ScrollTo | DateTime? | Initial scroll position in time list | null |
Min | DateTime | Minimum selectable time | 00:00 |
Max | DateTime | Maximum selectable time | 23:59 |
AllowEdit | bool | Allow manual text input | true |
StrictMode | bool | Enforce strict input validation | false |
EnableMask | bool | Enable input masking | false |
OpenOnFocus | bool | Open popup when input is focused | false |
FloatLabelType | FloatLabelType | Float label behavior | Never |
Enabled | bool | Enable/disable component | true |
Readonly | bool | Read-only mode | false |
ShowClearButton | bool | Show clear button | false |
EnableRtl | bool | Enable right-to-left (RTL) direction | false |
FullScreen | bool | Full-screen mode on mobile | false |
ZIndex | int | Z-index for popup | 1000 |
Width | string | Component width | "100%" |
CssClass | string | Custom CSS class | null |
TabIndex | int | Tab order index | 0 |
Documentation Navigation
Getting Started
📄 Read: references/getting-started.md
- NuGet package installation
- Namespace imports
- Service registration in Program.cs
- Theme setup and inclusion
- Basic component implementation
- Step property and time intervals
Time Formats
📄 Read: references/time-formats.md
- Display format customization
- Input format configuration
- Standard vs custom format strings
- Culture-based default formats
- 12-hour and 24-hour format examples
- When to use each format option
Data Binding
📄 Read: references/data-binding.md
- One-way binding patterns
- Two-way binding with @bind-Value
- Dynamic value updates
- DateTime and DateTime? type handling
- Value change event integration
Events and Handlers
📄 Read: references/events-and-handlers.md
- ValueChange event (EventCallback<ChangeEventArgs<TValue>>)
- OnOpen/OnClose popup events
- Selected event (time selection in list)
- OnItemRender event (custom time list item rendering)
- Focus/Blur input events
- Cleared event (clear button clicked)
- Created/Destroyed lifecycle events
- Using TimePickerEvents child component
- Event handler implementation patterns
Styling and Appearance
📄 Read: references/styling-and-appearance.md
- CSS classes for customization
- Container element styling
- Icon element styling
- Popup and list item styling
- Full-screen mode for mobile devices
- Theme integration (Bootstrap, Material, Fluent)
Accessibility and Globalization
📄 Read: references/accessibility-and-globalization.md
- WCAG 2.2 compliance and standards
- Keyboard navigation shortcuts (arrow keys, Enter, Esc)
- WAI-ARIA attributes and roles
- RTL (right-to-left) support
- Localization and culture configuration
- Screen reader support
Mask Support
📄 Read: references/mask-support.md
- EnableMask property for input masking
- TimePickerMaskPlaceholder directive
- Custom placeholder characters (Hour, Minute, Second)
- Format-specific masking patterns
- Input validation with masks
Common Patterns
Pattern 1: Simple Time Selection
When users need a basic time picker without complex requirements:
<SfTimePicker TValue="DateTime?"
@bind-Value="@AppointmentTime"
Placeholder="Select appointment time">
</SfTimePicker>Pattern 2: Business Hours Only
When time selection should be limited to specific hours:
<SfTimePicker TValue="DateTime?"
@bind-Value="@BusinessTime"
Min="@new DateTime(2026, 1, 1, 09, 0, 0)"
Max="@new DateTime(2026, 1, 1, 17, 0, 0)"
Step=30
Format="HH:mm">
</SfTimePicker>
@code {
public DateTime? BusinessTime { get; set; }
}Pattern 3: 12-Hour Format with AM/PM
When displaying time in 12-hour format:
<SfTimePicker TValue="DateTime?"
@bind-Value="@UserTime"
Format="hh:mm tt"
Placeholder="Select time (12-hour)">
</SfTimePicker>
@code {
public DateTime? UserTime { get; set; } = DateTime.Now;
}Pattern 4: With Event Handling
When tracking time selection changes:
<SfTimePicker TValue="DateTime?">
<TimePickerEvents TValue="DateTime?" ValueChange="@OnTimeChanged"></TimePickerEvents>
</SfTimePicker>
@code {
private void OnTimeChanged(ChangeEventArgs<DateTime?> args)
{
Console.WriteLine($"Time selected: {args.Value}");
}
}Common Use Cases
1. Appointment Booking: Time selection for scheduling appointments with business hours validation 2. Time Tracking: Recording start/end times for timesheets or activity logs 3. Shift Management: Selecting shift times in HR/workforce applications 4. Travel Booking: Departure/arrival time selection for flights, trains 5. Delivery Windows: Setting preferred delivery time slots in e-commerce 6. Broadcast Scheduling: Selecting broadcast times for media applications 7. Meeting Scheduler: Time selection for virtual meetings with timezone support 8. Gym Booking: Class time selection in fitness management apps
Prerequisites
- Blazor WebAssembly or Blazor Server project (.NET 7 or later)
- NuGet package:
Syncfusion.Blazor.Calendars - NuGet package:
Syncfusion.Blazor.Themes - Syncfusion service registered in
Program.cs
---
Ready to implement Calendar components? Start with Getting Started guides above for setup, then navigate to other references based on your specific needs.
---
Next Steps: Start with the Getting Started guide for your chosen component, then navigate to other references based on your specific task.
For detailed implementation patterns, complete code examples, and troubleshooting guidance, read the appropriate reference file based on your specific needs.
````
Accessibility & Keyboard Navigation
Table of Contents
- Accessibility Standards
- ARIA Attributes
- Keyboard Navigation
- Screen Reader Support
- Testing for Accessibility
- Best Practices
---
Accessibility Standards
The Syncfusion Blazor Calendar meets strict accessibility standards:
Compliance Levels
| Standard | Status | Details |
|---|---|---|
| WCAG 2.2 Level AA | ✅ Compliant | Web Content Accessibility Guidelines |
| WCAG 2.2 Level AAA | ⚠️ Partial | Enhanced accessibility |
| Section 508 | ⚠️ Partial | US Federal accessibility |
| ADA | ✅ Compliant | Americans with Disabilities Act |
| ARIA 1.2 | ✅ Compliant | Accessible Rich Internet Applications |
What This Means
- Keyboard accessible - Fully navigable via keyboard
- Screen reader compatible - Works with NVDA, JAWS, VoiceOver
- Color contrast - Meets WCAG AA (4.5:1 for text)
- Focus management - Clear visible focus indicators
- Semantic HTML - Proper structure for assistive tech
---
ARIA Attributes
What are ARIA Attributes?
ARIA (Accessible Rich Internet Applications) attributes enhance semantics for assistive technologies:
<div role="grid" aria-label="Date picker calendar">
<div role="gridcell" aria-selected="false" aria-disabled="false">5</div>
<div role="gridcell" aria-selected="true" aria-disabled="false">15</div>
</div>Calendar ARIA Attributes
| Attribute | Purpose | Example |
|---|---|---|
role="grid" | Calendar is a grid structure | Applied to calendar table |
role="gridcell" | Each day is a grid cell | Applied to each day <td> |
aria-label | Text label for screen reader | "Previous month" on nav buttons |
aria-selected | Current selected date | aria-selected="true" |
aria-disabled | Out-of-range or disabled dates | aria-disabled="true" |
aria-activedescendant | Currently focused item | Points to focused date ID |
tabindex | Keyboard focus order | tabindex="0" for interactive |
Example: ARIA Implementation
Syncfusion automatically adds ARIA attributes:
<!-- Automatic ARIA markup (rendered by Syncfusion) -->
<table role="grid" aria-label="Date picker calendar">
<thead>
<tr role="row">
<th>Sun</th>
<th>Mon</th>
<!-- ... -->
</tr>
</thead>
<tbody>
<tr role="row">
<td role="gridcell" aria-selected="false">1</td>
<td role="gridcell" aria-selected="true" class="e-selected">15</td>
<td role="gridcell" aria-disabled="true">30</td>
</tr>
</tbody>
</table>Screen Reader Announcement
When user focuses on a date cell, screen reader announces:
"15, selected, Tuesday, March 2024"---
Keyboard Navigation
Supported Keyboard Shortcuts
The Calendar provides comprehensive keyboard support:
Navigation Keys
| Key | Action |
|---|---|
↑ | Move to same day of previous week |
↓ | Move to same day of next week |
← | Move to previous day |
→ | Move to next day |
Home | Move to first day of month |
End | Move to last day of month |
Page Up | Move to same date of previous month |
Page Down | Move to same date of next month |
Shift + Page Up | Move to same date of previous year |
Shift + Page Down | Move to same date of next year |
View Navigation
| Key Combination | Action |
|---|---|
Ctrl + ↑ | Drill-up to broader view (Month → Year) |
Ctrl + ↓ | Drill-down to detailed view (Year → Month) |
Ctrl + Home | Jump to first date of year |
Ctrl + End | Jump to last date of year |
Selection & Entry
| Key | Action |
|---|---|
Enter | Select focused date |
Space | Select/toggle focused date |
Example: Testing Keyboard Navigation
@using Syncfusion.Blazor.Calendars
<h3>Calendar - Try Keyboard Navigation</h3>
<p><strong>Instructions:</strong> Click the calendar and use arrow keys to navigate.</p>
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate"></SfCalendar>
<div style="margin-top: 20px; padding: 10px; background-color: #f0f0f0; border-radius: 4px;">
<h4>Keyboard Shortcuts:</h4>
<ul>
<li><strong>Arrow Keys:</strong> Navigate days/months</li>
<li><strong>Home/End:</strong> Go to first/last day of month</li>
<li><strong>Page Up/Down:</strong> Previous/next month</li>
<li><strong>Ctrl + Arrow:</strong> Change view level</li>
<li><strong>Enter:</strong> Select focused date</li>
</ul>
<p style="margin-top: 10px;"><strong>Selected Date:</strong> @SelectedDate?.ToString("dddd, dd MMMM yyyy")</p>
</div>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
}Keyboard Navigation Flow
1. Tab into calendar - Focus moves to calendar container 2. Arrow keys - Navigate cells (24 cells visible on screen) 3. Enter - Select focused date 4. Tab out - Focus moves to next interactive element 5. Shift+Tab - Move backward through focus order
---
Screen Reader Support
Supported Screen Readers
- NVDA (Windows, free)
- JAWS (Windows, commercial)
- VoiceOver (Mac/iOS, built-in)
- TalkBack (Android, built-in)
What Screen Reader Users Hear
When navigating calendar:
// Initially loading calendar
"Calendar, month view. March 2024. Instructions: Use arrow keys to navigate dates."
// Focusing on a date
"15, selected, Tuesday, March 19, 2024"
// Focusing on disabled date (out of range)
"30, disabled, Friday, March 29, 2024"
// Drilling up to year view
"Year 2024, list of months"
// Focusing on month
"March 2024, clickable"Best Practices for Screen Reader Users
1. Provide context - Explain calendar purpose before component 2. Label calendar - Use descriptive aria-label 3. Announce selections - Read back selected date 4. Guide navigation - Explain available keyboard shortcuts
Example: Screen Reader Friendly Component
@using Syncfusion.Blazor.Calendars
<h3>Accessible Appointment Booking</h3>
<!-- Instruction text for screen reader users -->
<div role="region" aria-label="Instructions for using calendar">
<p>Select your appointment date using the calendar below. Use arrow keys to navigate, Enter to select.</p>
</div>
<!-- Calendar with descriptive label -->
<div>
<label for="appointment-calendar">Appointment Date (Required)</label>
<SfCalendar TValue="DateTime?"
@bind-Value="@AppointmentDate"
id="appointment-calendar"
aria-label="Select appointment date - available dates shown">
</SfCalendar>
</div>
<!-- Announce selected date -->
<div role="status" aria-live="polite" aria-atomic="true">
@if (AppointmentDate != null)
{
<p>Appointment selected for @AppointmentDate.Value.ToString("dddd, MMMM d, yyyy")</p>
}
</div>
@code {
public DateTime? AppointmentDate { get; set; }
}---
Testing for Accessibility
Manual Testing Checklist
Keyboard Navigation
- [ ] Can tab into calendar
- [ ] Arrow keys move focus predictably
- [ ] Page Up/Down work
- [ ] Can enter/year views with Ctrl+arrow
- [ ] Enter/Space select dates
- [ ] Can tab out of calendar
- [ ] No keyboard traps
Screen Reader
- [ ] Calendar identified as grid/calendar
- [ ] Date cells have proper roles
- [ ] Selected/disabled states announced
- [ ] Month/year header announced
- [ ] Navigation buttons labeled
- [ ] Instructions provided or documented
Visual Design
- [ ] Focus indicator clearly visible
- [ ] Color not sole indicator (redundant cues)
- [ ] Text contrast ≥4.5:1 (AA) or ≥7:1 (AAA)
- [ ] Text is resizable to 200%
- [ ] No text smaller than 12px (unless necessary)
Mobile/Touch
- [ ] Touch targets ≥44x44px
- [ ] Zoom works correctly
- [ ] Screen reader gestures work
Automated Testing Tools
Browser DevTools Accessibility Audit
1. Press F12 (Developer Tools) 2. Go to "Lighthouse" tab 3. Select "Accessibility" 4. Run audit 5. Review violations
Free Tools
- axe DevTools - Browser extension
- Accessibility Checker - Web validator
- WebAIM WAVE - Web accessibility evaluator
- Lighthouse - Built into Chrome DevTools
Example: Running Accessibility Audit
# Using axe-core in Playwright tests
npm install --save-dev @axe-core/playwright
# Test calendar component for violations
const axe = require('axe-core');
// Run axe on calendar element
// Check results for violations---
Best Practices
1. Always Label Form Controls
Bad:
<SfCalendar TValue="DateTime?" @bind-Value="@Date"></SfCalendar>Good:
<label for="event-date">Event Date (Required)</label>
<SfCalendar TValue="DateTime?"
@bind-Value="@Date"
id="event-date"
aria-describedby="date-help">
</SfCalendar>
<p id="date-help">Select a date at least 7 days in the future.</p>2. Provide Error Messages
Bad:
@if (!IsValidDate(Date))
{
<p style="color: red;">Invalid date</p>
}Good:
<div role="alert" aria-live="assertive">
@if (!IsValidDate(Date))
{
<p style="color: red;">❌ Invalid date: must be in future</p>
}
</div>3. Ensure Sufficient Color Contrast
Bad:
/* Light gray on white - less than 3:1 contrast */
.e-calendar .e-day { color: #d0d0d0; }Good:
/* Dark gray on white - more than 4.5:1 contrast */
.e-calendar .e-day { color: #333333; }4. Avoid Color-Only Indicators
Bad:
<!-- Red dates are unavailable (color-blind users won't know) -->
<span style="background-color: red">5</span>Good:
<!-- Red + disabled state + icon -->
<span style="background-color: red" aria-disabled="true">
5 <span aria-label="not available">✗</span>
</span>5. Provide Keyboard Alternatives
Bad:
<div @onmouseenter="ShowPopup">Hover for info</div>Good:
<button @onmouseenter="ShowPopup" @onfocus="ShowPopup">
Info <span aria-label="keyboard accessible">ℹ️</span>
</button>6. Test with Real Users
The best accessibility practice is testing with actual users with disabilities:
- Keyboard-only users
- Screen reader users
- Low vision users
- Mobile/touch users
- Color-blind users
7. Document Accessibility Features
In your component documentation:
## Accessibility
This calendar component:
- Supports keyboard navigation (arrow keys, Enter, Page Up/Down)
- Works with screen readers (NVDA, JAWS, VoiceOver)
- Meets WCAG 2.2 Level AA standards
- Includes focus indicators
- Supports high contrast mode
Keyboard shortcuts:
- ↑/↓/←/→: Navigate dates
- Enter: Select date
- Ctrl+↑: Zoom out to year view
- Ctrl+↓: Zoom in to day view---
Accessibility in Your Applications
Creating Inclusive Date Selection Experience
@using Syncfusion.Blazor.Calendars
<div class="booking-section" role="region" aria-label="Appointment booking form">
<!-- Instructions -->
<div class="instructions" role="note">
<h2>Book Your Appointment</h2>
<p>Use the calendar below to select your preferred date.
Keyboard users: Use arrow keys to navigate, Enter to select.
Screen reader users: Available dates will be announced.</p>
</div>
<!-- Calendar -->
<fieldset>
<legend>Select Appointment Date (Required)</legend>
<SfCalendar TValue="DateTime?"
@bind-Value="@AppointmentDate"
Min="@minAppointmentDate"
Max="@maxAppointmentDate">
<CalendarEvents TValue="DateTime?"
ValueChange="@OnDateChanged"
OnRenderDayCell="@MarkBooked">
</CalendarEvents>
</SfCalendar>
</fieldset>
<!-- Confirmation -->
<div role="status" aria-live="polite" aria-atomic="true" class="confirmation">
@if (AppointmentDate != null)
{
<p>✓ Appointment confirmed for <strong>@AppointmentDate.Value.ToString("dddd, MMMM d, yyyy")</strong></p>
}
</div>
<!-- Error Messages -->
@if (HasError)
{
<div role="alert" class="error-message">
<p>❌ @ErrorMessage</p>
</div>
}
<!-- Submit -->
<button @onclick="SubmitBooking" disabled="@(AppointmentDate == null)">
Confirm Booking
</button>
</div>
@code {
public DateTime? AppointmentDate { get; set; }
public bool HasError { get; set; }
public string ErrorMessage { get; set; } = "";
private DateTime minAppointmentDate = DateTime.Now;
private DateTime maxAppointmentDate = DateTime.Now.AddDays(90);
private HashSet<int> BookedDates = new() { 5, 12, 19, 26 };
private void OnDateChanged(ChangedEventArgs<DateTime?> args)
{
if (args.Value != null && BookedDates.Contains(args.Value.Value.Day))
{
HasError = true;
ErrorMessage = "This date is already booked. Please select another.";
AppointmentDate = null;
}
else
{
HasError = false;
}
}
private void MarkBooked(RenderDayCellEventArgs args)
{
if (BookedDates.Contains(args.Date.Day))
{
args.IsDisabled = true;
args.ClassList.Add("booked");
}
}
private async Task SubmitBooking()
{
if (AppointmentDate == null)
return;
// Submit appointment
Console.WriteLine($"Booking appointment for {AppointmentDate}");
}
}
<style>
.booking-section {
max-width: 600px;
margin: 20px auto;
padding: 20px;
}
.instructions {
background-color: #e3f2fd;
padding: 12px;
border-left: 4px solid #1976d2;
margin-bottom: 20px;
}
.confirmation {
color: #4caf50;
padding: 10px;
background-color: #e8f5e9;
border-radius: 4px;
margin: 10px 0;
}
.error-message {
color: #d32f2f;
padding: 10px;
background-color: #ffebee;
border-radius: 4px;
margin: 10px 0;
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
button:focus {
outline: 3px solid #1976d2;
outline-offset: 2px;
}
</style>---
Resources
Advanced Features & Patterns
Table of Contents
- Show/Hide Other Month Dates
- Multiple Date Selection
- Week Number Display
- Custom Cell Rendering
- Performance Optimization
- Integration Patterns
- Complex Use Cases
---
Show/Hide Other Month Dates
What Does This Do?
By default, Calendar shows trailing dates from the previous month and leading dates from the next month to fill the grid:
March 2024
S M T W T F S
25 26 27 28 29 1 2 <- Feb dates (other month)
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31 1 2 3 4 5 6 <- Apr dates (other month)Hiding Other Month Dates
While Syncfusion Calendar doesn't have a built-in toggle, you can hide them with CSS:
/* Hide dates from other months */
.e-calendar .e-other-month {
visibility: hidden;
}
/* Alternative: Disable them */
.e-calendar .e-other-month {
opacity: 0.3;
pointer-events: none;
}Custom Rendering Approach
Use OnRenderDayCell event to customize other month dates:
@using Syncfusion.Blazor.Calendars
<h3>Calendar - Show/Hide Other Month Dates</h3>
<div>
<button @onclick="() => ToggleOtherMonthDates()">
@(ShowOtherMonthDates ? "Hide" : "Show") Other Month Dates
</button>
</div>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@CustomizeOtherMonthDates"></CalendarEvents>
</SfCalendar>
<style>
.hidden-other-month {
opacity: 0 !important;
pointer-events: none !important;
}
</style>
@code {
public bool ShowOtherMonthDates { get; set; } = true;
private void ToggleOtherMonthDates()
{
ShowOtherMonthDates = !ShowOtherMonthDates;
}
private void CustomizeOtherMonthDates(RenderDayCellEventArgs args)
{
if (args.IsOutOfRange && !ShowOtherMonthDates)
{
args.ClassList.Add("hidden-other-month");
}
}
}---
Multiple Date Selection
Use Case
Select multiple dates (vacation period, multiple meetings, etc.)
Implementation
While Calendar doesn't natively support multiple selection, you can implement it:
@using Syncfusion.Blazor.Calendars
<h3>Multi-Date Selection (Trip Planning)</h3>
<div class="selection-info">
<p>Selected Dates: @(SelectedDates.Count > 0 ? string.Join(", ", SelectedDates.Select(d => d.ToString("dd/MM"))) : "None")</p>
<button @onclick="ClearSelection">Clear All</button>
</div>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?"
ValueChange="@AddToSelection"
OnRenderDayCell="@HighlightSelected">
</CalendarEvents>
</SfCalendar>
<style>
.selected-date {
background-color: #bbdefb !important;
border: 2px solid #1976d2 !important;
}
.start-date {
background: linear-gradient(to right, #1976d2 50%, #bbdefb 50%) !important;
color: white !important;
}
.end-date {
background: linear-gradient(to left, #1976d2 50%, #bbdefb 50%) !important;
color: white !important;
}
</style>
@code {
public HashSet<DateTime> SelectedDates { get; set; } = new();
private void AddToSelection(ChangedEventArgs<DateTime?> args)
{
if (args.Value.HasValue)
{
if (SelectedDates.Contains(args.Value.Value.Date))
SelectedDates.Remove(args.Value.Value.Date);
else
SelectedDates.Add(args.Value.Value.Date);
}
}
private void HighlightSelected(RenderDayCellEventArgs args)
{
if (SelectedDates.Contains(args.Date.Date))
{
args.ClassList.Add("selected-date");
var minDate = SelectedDates.Min();
var maxDate = SelectedDates.Max();
if (args.Date.Date == minDate)
args.ClassList.Add("start-date");
if (args.Date.Date == maxDate)
args.ClassList.Add("end-date");
}
}
private void ClearSelection()
{
SelectedDates.Clear();
}
}Range Selection Pattern
@using Syncfusion.Blazor.Calendars
<h3>Date Range Selection (Vacation)</h3>
<div class="range-inputs">
<div>
<label>From:</label>
<input type="date" @bind="@StartDateString" />
</div>
<div>
<label>To:</label>
<input type="date" @bind="@EndDateString" />
</div>
<p>Duration: @((EndDate?.Date - StartDate?.Date)?.Days) days</p>
</div>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@HighlightRange"></CalendarEvents>
</SfCalendar>
<style>
.range-highlight {
background-color: #e1bee7 !important;
}
.range-start {
background-color: #7b1fa2 !important;
color: white !important;
}
.range-end {
background-color: #7b1fa2 !important;
color: white !important;
}
</style>
@code {
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string StartDateString
{
get => StartDate?.ToString("yyyy-MM-dd");
set => StartDate = DateTime.TryParse(value, out var dt) ? dt : null;
}
public string EndDateString
{
get => EndDate?.ToString("yyyy-MM-dd");
set => EndDate = DateTime.TryParse(value, out var dt) ? dt : null;
}
private void HighlightRange(RenderDayCellEventArgs args)
{
if (StartDate == null || EndDate == null) return;
var min = StartDate.Value.Date < EndDate.Value.Date ? StartDate.Value.Date : EndDate.Value.Date;
var max = StartDate.Value.Date > EndDate.Value.Date ? StartDate.Value.Date : EndDate.Value.Date;
if (args.Date.Date >= min && args.Date.Date <= max)
{
args.ClassList.Add("range-highlight");
if (args.Date.Date == min)
args.ClassList.Add("range-start");
if (args.Date.Date == max)
args.ClassList.Add("range-end");
}
}
}---
Week Number Display
Enabling Week Numbers
<SfCalendar TValue="DateTime?" ShowWeekNumbers="true"></SfCalendar>Output: Shows ISO 8601 week numbers in left column (1-53)
Week Number Details
- Standard: ISO 8601 (International)
- Week 1: First week with Thursday of the year
- Range: 1-53
- Use: Project planning, reporting periods, compliance
Example: Week-Based Planning
@using Syncfusion.Blazor.Calendars
<h3>Sprint Planning (By Week Number)</h3>
<SfCalendar TValue="DateTime?"
@bind-Value="@SelectedDate"
ShowWeekNumbers="true">
<CalendarEvents TValue="DateTime?"
ValueChange="@OnDateSelected"
Navigated="@OnNavigated">
</CalendarEvents>
</SfCalendar>
<div class="sprint-info">
<h5>Sprint Details</h5>
<p>Date: @SelectedDate?.ToString("dddd, dd MMMM yyyy")</p>
<p>Week Number: @GetWeekNumber(SelectedDate)</p>
<p>Sprint: @GetSprintName(SelectedDate)</p>
<p>Work Days Remaining: @GetWorkDaysRemaining(SelectedDate)</p>
</div>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
private int GetWeekNumber(DateTime? date)
{
if (date == null) return 0;
var culture = System.Globalization.CultureInfo.GetCultureInfo("en-US");
return culture.Calendar.GetWeekOfYear(date.Value,
System.Globalization.CalendarWeekRule.FirstFourDayWeek,
DayOfWeek.Monday);
}
private string GetSprintName(DateTime? date)
{
if (date == null) return "";
int week = GetWeekNumber(date);
int sprint = (week - 1) / 2 + 1;
return $"Sprint Q{date.Value.Year}/{sprint}";
}
private int GetWorkDaysRemaining(DateTime? date)
{
if (date == null) return 0;
var sundayOfWeek = date.Value.AddDays(-(int)date.Value.DayOfWeek);
var fridayOfWeek = sundayOfWeek.AddDays(5);
return (fridayOfWeek - date.Value).Days;
}
private void OnDateSelected(ChangedEventArgs<DateTime?> args)
{
// Trigger sprint calculation
StateHasChanged();
}
private void OnNavigated(NavigatedEventArgs args)
{
// Update sprint info when navigating
}
}---
Custom Cell Rendering
Advanced Rendering Scenarios
Scenario 1: Business Hours Indicator
@using Syncfusion.Blazor.Calendars
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@ShowBusinessHours"></CalendarEvents>
</SfCalendar>
<style>
.business-hours::after {
content: "9-5";
font-size: 10px;
opacity: 0.6;
}
.after-hours {
opacity: 0.5;
}
</style>
@code {
private void ShowBusinessHours(RenderDayCellEventArgs args)
{
if (args.Date.DayOfWeek != DayOfWeek.Saturday &&
args.Date.DayOfWeek != DayOfWeek.Sunday)
{
args.ClassList.Add("business-hours");
}
else
{
args.ClassList.Add("after-hours");
}
}
}Scenario 2: Heat Map (Intensity Visualization)
@using Syncfusion.Blazor.Calendars
<h3>Activity Heatmap</h3>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@ColorByIntensity"></CalendarEvents>
</SfCalendar>
<style>
.intensity-0 { background-color: #ffffff; }
.intensity-1 { background-color: #eef5e9; }
.intensity-2 { background-color: #c3e88d; }
.intensity-3 { background-color: #9ccc65; }
.intensity-4 { background-color: #7cb342; }
.intensity-5 { background-color: #558b2f; }
</style>
@code {
private Dictionary<int, int> ActivityIntensity = new()
{
{ 1, 2 }, { 2, 3 }, { 3, 1 }, { 5, 4 },
{ 10, 5 }, { 15, 3 }, { 20, 2 }, { 25, 4 }
};
private void ColorByIntensity(RenderDayCellEventArgs args)
{
int intensity = ActivityIntensity.ContainsKey(args.Date.Day)
? ActivityIntensity[args.Date.Day]
: 0;
args.ClassList.Add($"intensity-{intensity}");
}
}---
Performance Optimization
Large Date Ranges
When working with large datasets:
// Lazy-load disabled dates instead of pre-computing all
private async Task<bool> IsDateDisabled(DateTime date)
{
// Fetch from API only when needed
var response = await Http.GetAsync($"/api/availability/{date:yyyy-MM-dd}");
return !response.IsSuccessStatusCode;
}Memoization for Calculations
private Dictionary<int, bool> HolidayCache = new();
private bool IsHoliday(DateTime date)
{
int dayOfYear = date.DayOfYear;
if (!HolidayCache.ContainsKey(dayOfYear))
{
HolidayCache[dayOfYear] = ComputeHolidayStatus(date);
}
return HolidayCache[dayOfYear];
}Avoid Heavy Operations in OnRenderDayCell
Bad:
private void OnRenderDayCell(RenderDayCellEventArgs args)
{
// Called for EVERY cell on EVERY render!
var isDisabled = Http.Get($"/api/availability/{args.Date}").IsSuccess; // ❌ Slow!
}Good:
private Dictionary<DateTime, bool> AvailabilityCache;
private void OnRenderDayCell(RenderDayCellEventArgs args)
{
// Use cached data
if (AvailabilityCache.ContainsKey(args.Date.Date))
{
args.IsDisabled = !AvailabilityCache[args.Date.Date];
}
}---
Integration Patterns
Pattern 1: Calendar + Data Grid
@using Syncfusion.Blazor.Calendars
@using Syncfusion.Blazor.Grids
<div class="calendar-grid-layout">
<div class="calendar-section">
<h5>Select Date:</h5>
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate"></SfCalendar>
</div>
<div class="grid-section">
<h5>Events for @SelectedDate?.ToString("dd/MM/yyyy"):</h5>
<SfGrid DataSource="@GetEventsForDate(SelectedDate)">
<GridColumns>
<GridColumn Field="@nameof(Event.Time)" HeaderText="Time"></GridColumn>
<GridColumn Field="@nameof(Event.Title)" HeaderText="Event"></GridColumn>
</GridColumns>
</SfGrid>
</div>
</div>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
public class Event
{
public string Time { get; set; }
public string Title { get; set; }
}
private List<Event> GetEventsForDate(DateTime? date)
{
if (date == null) return new();
// Filter events for selected date
return new()
{
new() { Time = "09:00", Title = "Stand-up" },
new() { Time = "14:00", Title = "Review" }
};
}
}
<style>
.calendar-grid-layout {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 20px;
}
</style>Pattern 2: Calendar Modal/Dialog
@using Syncfusion.Blazor.Calendars
@using Syncfusion.Blazor.Popups
<button @onclick="@ShowCalendarDialog">Pick Date</button>
<SfDialog @bind-Visible="@IsDialogOpen" Title="Select Date" Width="400px">
<DialogTemplates>
<Content>
<SfCalendar TValue="DateTime?" @bind-Value="@DialDate"></SfCalendar>
</Content>
</DialogTemplates>
<DialogButtons>
<DialogButton Content="OK" OnClick="@ConfirmSelection" />
<DialogButton Content="Cancel" OnClick="@CancelSelection" />
</DialogButtons>
</SfDialog>
@code {
public bool IsDialogOpen { get; set; }
public DateTime? DialDate { get; set; }
private void ShowCalendarDialog()
{
IsDialogOpen = true;
}
private void ConfirmSelection()
{
IsDialogOpen = false;
// Use DialDate
}
private void CancelSelection()
{
IsDialogOpen = false;
}
}---
Complex Use Cases
Use Case 1: Appointment Slots
@using Syncfusion.Blazor.Calendars
<h3>Schedule Appointment</h3>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?"
ValueChange="@OnDateSelected"
OnRenderDayCell="@MarkAvailable">
</CalendarEvents>
</SfCalendar>
@if (AvailableSlots.Count > 0)
{
<div class="time-slots">
<h5>Available Times:</h5>
<div class="slots">
@foreach (var slot in AvailableSlots)
{
<button @onclick="@(() => SelectSlot(slot))" class="slot">
@slot.ToString("HH:mm")
</button>
}
</div>
</div>
}
@code {
private DateTime? SelectedDate { get; set; }
private List<DateTime> AvailableSlots { get; set; } = new();
private void OnDateSelected(ChangedEventArgs<DateTime?> args)
{
SelectedDate = args.Value;
LoadAvailableSlots(SelectedDate);
}
private void LoadAvailableSlots(DateTime? date)
{
if (date == null) return;
AvailableSlots = new()
{
date.Value.AddHours(9),
date.Value.AddHours(10),
date.Value.AddHours(14),
date.Value.AddHours(15)
};
}
private void MarkAvailable(RenderDayCellEventArgs args)
{
// Mark dates with available slots
if (HasAvailableSlots(args.Date))
{
args.ClassList.Add("has-slots");
}
}
private bool HasAvailableSlots(DateTime date) => true; // Implement logic
private void SelectSlot(DateTime slot)
{
Console.WriteLine($"Selected: {slot}");
}
}
<style>
.time-slots {
margin-top: 20px;
}
.slots {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
gap: 10px;
}
.slot {
padding: 10px;
border: 1px solid #ddd;
background: white;
cursor: pointer;
border-radius: 4px;
}
.slot:hover {
background: #e3f2fd;
}
</style>Use Case 2: Recurring Events
@using Syncfusion.Blazor.Calendars
<h3>Recurring Events Calendar</h3>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@HighlightRecurring"></CalendarEvents>
</SfCalendar>
@code {
private class RecurringEvent
{
public string Title { get; set; }
public DayOfWeek DayOfWeek { get; set; }
public string Color { get; set; }
}
private List<RecurringEvent> RecurringEvents = new()
{
new() { Title = "Team Meeting", DayOfWeek = DayOfWeek.Monday, Color = "blue" },
new() { Title = "Standup", DayOfWeek = DayOfWeek.Wednesday, Color = "green" },
new() { Title = "Review", DayOfWeek = DayOfWeek.Friday, Color = "purple" }
};
private void HighlightRecurring(RenderDayCellEventArgs args)
{
var recurringToday = RecurringEvents
.FirstOrDefault(e => e.DayOfWeek == args.Date.DayOfWeek);
if (recurringToday != null)
{
args.ClassList.Add($"recurring-{recurringToday.Color}");
}
}
}---
Summary
Advanced Calendar features enable:
- ✅ Complex date selection patterns
- ✅ Data visualization (heatmaps, intensity)
- ✅ Integration with other components
- ✅ Performance-optimized rendering
- ✅ Enterprise-grade functionality
For production applications, combine these patterns with proper error handling, loading states, and user feedback.
Calendar Views & Navigation
Table of Contents
- View Types Overview
- Start Property
- Depth Property
- View Restrictions
- Drill-Down Navigation
- Common Patterns
- Examples
---
View Types Overview
The Blazor Calendar provides three hierarchical views for date selection:
| View | Level | Displays | Use Case |
|---|---|---|---|
| Month | Detailed | Days in current month | Precise date selection |
| Year | Middle | Months in current year | Month-level selection |
| Decade | Broad | Years in current decade | Year-level selection |
View Hierarchy
Decade (broadest)
↓
Year
↓
Month (most detailed)---
Start Property
Purpose
The Start property sets the initial view displayed when the Calendar renders. It also acts as the upper limit for drill-up navigation (you cannot navigate to broader views than Start).
Syntax
<SfCalendar TValue="DateTime?" Start="CalendarView.Month"></SfCalendar>Values
CalendarView.Month- Shows day grid (default)CalendarView.Year- Shows month gridCalendarView.Decade- Shows year grid
Examples
Example 1: Start with Month View (Default)
@using Syncfusion.Blazor.Calendars
<SfCalendar TValue="DateTime?" Start="CalendarView.Month"></SfCalendar>Output: Calendar displays current month with days. Clicking month header allows drill-up to Year view.
Example 2: Start with Year View
@using Syncfusion.Blazor.Calendars
<SfCalendar TValue="DateTime?" Start="CalendarView.Year"></SfCalendar>Output: Calendar shows current year with months. Cannot navigate beyond Year view (no Decade view available). Clicking a month drills down to that month's days.
Example 3: Start with Decade View
@using Syncfusion.Blazor.Calendars
<SfCalendar TValue="DateTime?" Start="CalendarView.Decade"></SfCalendar>Output: Calendar displays years in current decade (e.g., 2020-2029). Cannot navigate beyond Decade. Clicking a year drills down to year's months.
---
Depth Property
Purpose
The Depth property sets the deepest (most detailed) view allowed. It acts as the lower limit for drill-down navigation. You cannot drill deeper than the Depth view.
Syntax
<SfCalendar TValue="DateTime?" Depth="CalendarView.Month"></SfCalendar>Values
CalendarView.Month- Most detailed allowedCalendarView.Year- Month-level is forbiddenCalendarView.Decade- Both Month and Year forbidden
Important Rules
1. Depth must be "smaller" (more detailed) than Start, otherwise navigation is disabled 2. If Start == Depth, the Calendar view is fixed and cannot change 3. Both properties must follow this hierarchy:
Start ≥ Depth (in terms of detail level)
Decade ≥ Year ≥ MonthExamples
Example 1: Year Selection Only
Restrict to Year view - cannot drill down to individual days:
@using Syncfusion.Blazor.Calendars
<SfCalendar TValue="DateTime?"
Start="CalendarView.Year"
Depth="CalendarView.Year">
</SfCalendar>Output: Calendar shows months; cannot drill down to individual days. Clicking a month does nothing (view is locked).
Example 2: Decade to Year Selection
Users drill from decade → year, but not to individual days:
@using Syncfusion.Blazor.Calendars
<SfCalendar TValue="DateTime?"
Start="CalendarView.Decade"
Depth="CalendarView.Year">
</SfCalendar>Output: Shows years in decade. Clicking a year shows its months. Cannot drill to individual days.
Example 3: Full Range (Default)
Allow all three views:
@using Syncfusion.Blazor.Calendars
<SfCalendar TValue="DateTime?"
Start="CalendarView.Decade"
Depth="CalendarView.Month">
</SfCalendar>Output: Decade → Year → Month hierarchy fully enabled.
---
View Restrictions
Use Cases
View restrictions are useful for: 1. Budget Selection - Allow year selection, not individual days 2. Report Period - Select month ranges, not specific dates 3. Preference Selection - Choose decade/era, not precise dates 4. Simplified UX - Remove navigation complexity for specific use cases
Restriction Patterns
Pattern 1: Month View Only (No Navigation)
<SfCalendar TValue="DateTime?"
Start="CalendarView.Month"
Depth="CalendarView.Month">
</SfCalendar>Use: Display current month only; no drilling or breadcrumb navigation.
Pattern 2: Year Selection Only
<SfCalendar TValue="DateTime?"
Start="CalendarView.Year"
Depth="CalendarView.Year">
</SfCalendar>Use: Pick a month; cannot select specific day or navigate to other years.
Pattern 3: Decade → Month (Skip Year)
<SfCalendar TValue="DateTime?"
Start="CalendarView.Decade"
Depth="CalendarView.Month">
</SfCalendar>Behavior: Decade → Month (no Year intermediate). Clicking a year shows month grid directly.
---
Drill-Down Navigation
What is Drill-Down?
Navigation from broader to more detailed views:
- Click month header in Month view → goes to Year view
- Click year header in Year view → goes to Decade view
Drill-Down Boundaries
- Start property limits drill-up (cannot go broader)
- Depth property limits drill-down (cannot go deeper)
Example: Restricted Drill-Down
@using Syncfusion.Blazor.Calendars
<h3>Select a date from March onwards (2024)</h3>
<SfCalendar TValue="DateTime?"
Start="CalendarView.Year"
Depth="CalendarView.Month"
Min="@(new DateTime(2024, 3, 1))"
Value="@SelectedDate">
</SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
}Behavior: 1. Displays year view (months) 2. Months before March are disabled 3. Clicking a month shows that month's days 4. Cannot click month header to go back to decade view (Start is Year)
---
Common Patterns
Pattern 1: Year Picker
Select year only, then month/day selected elsewhere:
<SfCalendar TValue="DateTime?"
Start="CalendarView.Decade"
Depth="CalendarView.Year">
</SfCalendar>Pattern 2: Month Picker
Select month within current year:
<SfCalendar TValue="DateTime?"
Start="CalendarView.Year"
Depth="CalendarView.Year">
</SfCalendar>Pattern 3: Standard Date Picker
Full three-level navigation:
<SfCalendar TValue="DateTime?"
Start="CalendarView.Decade"
Depth="CalendarView.Month">
</SfCalendar>Pattern 4: Today-Only View
Display specific month as fixed view:
<SfCalendar TValue="DateTime?"
Start="CalendarView.Month"
Depth="CalendarView.Month"
Value="@DateTime.Now">
</SfCalendar>---
Examples
Example 1: Basic View Navigation
@using Syncfusion.Blazor.Calendars
<h3>Calendar with Year/Month/Decade Navigation</h3>
<p>Selected: @SelectedDate?.ToString("dd/MM/yyyy")</p>
<SfCalendar TValue="DateTime?"
@bind-Value="@SelectedDate"
Start="CalendarView.Decade"
Depth="CalendarView.Month">
</SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
}Interaction: 1. Shows decade (e.g., 2020-2029) 2. Click a year → shows that year's months 3. Click a month → shows that month's days 4. Click a day → date selected
Example 2: Year Constraint + View Restriction
@using Syncfusion.Blazor.Calendars
<h3>Select Year Between 2022-2025</h3>
<SfCalendar TValue="DateTime?"
Value="@SelectedDate"
Start="CalendarView.Decade"
Depth="CalendarView.Year"
Min="@(new DateTime(2022, 1, 1))"
Max="@(new DateTime(2025, 12, 31))">
</SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = new DateTime(2024, 1, 1);
}Behavior: Year selection (months per year) with years outside 2022-2025 disabled.
Example 3: Switchable Views
@using Syncfusion.Blazor.Calendars
<h3>Choose View Level</h3>
<div>
<button @onclick="() => SetDepth(CalendarView.Month)">Day Picker</button>
<button @onclick="() => SetDepth(CalendarView.Year)">Month Picker</button>
<button @onclick="() => SetDepth(CalendarView.Decade)">Year Picker</button>
</div>
<p>Selected: @SelectedDate</p>
<SfCalendar TValue="DateTime?"
Value="@SelectedDate"
Start="CalendarView.Decade"
Depth="@CurrentDepth">
</SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
public CalendarView CurrentDepth { get; set; } = CalendarView.Month;
private void SetDepth(CalendarView view)
{
CurrentDepth = view;
}
}Output: Buttons toggle between Day/Month/Year selection modes.
Example 4: Restricted Historic Dates
@using Syncfusion.Blazor.Calendars
<h3>Select a historical date (1900-1950)</h3>
<SfCalendar TValue="DateTime?"
Value="@SelectedDate"
Start="CalendarView.Decade"
Depth="CalendarView.Month"
Min="@(new DateTime(1900, 1, 1))"
Max="@(new DateTime(1950, 12, 31))">
</SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = new DateTime(1925, 6, 15);
}Output: Calendar starts in 1900s decade view; full drill-down available; years/months outside 1900-1950 are disabled.
---
Keyboard Navigation
When views are unrestricted, use keyboard shortcuts for navigation:
| Key | Action |
|---|---|
Ctrl + ↑ | Drill-up to broader view (Month → Year → Decade) |
Ctrl + ↓ | Drill-down to detailed view (Decade → Year → Month) |
Arrow Keys | Navigate within current view |
Enter | Select current item |
---
Edge Cases & Best Practices
Edge Case 1: Invalid Start/Depth Combination
Bad:
<SfCalendar Start="CalendarView.Month" Depth="CalendarView.Year"></SfCalendar>Problem: Depth (Year) is broader than Start (Month), which violates hierarchy. Navigation disabled.
Fix:
<SfCalendar Start="CalendarView.Year" Depth="CalendarView.Month"></SfCalendar>Edge Case 2: Fixed View
If Start == Depth, the view never changes:
<SfCalendar Start="CalendarView.Year" Depth="CalendarView.Year"></SfCalendar>Result: Month picker with no drill-up/down capability.
Best Practices
1. Always ensure: Start ≥ Depth in hierarchy (Decade ≥ Year ≥ Month) 2. Combine with Min/Max for date range + view restriction 3. Test keyboard navigation if drill-down is enabled 4. Provide feedback on selected view (show selected year/month in header) 5. Document restrictions for users (e.g., "Year selection only")
Date Selection & Data Binding
Table of Contents
- Overview
- One-Way Binding
- Two-Way Binding
- DateOnly Support
- Dynamic Value Changes
- Date Range Constraints
- Common Patterns
---
Overview
The Calendar component supports multiple data binding approaches:
| Pattern | Syntax | Use Case |
|---|---|---|
| One-Way | Value="@Date" | Display date, no auto-update |
| Two-Way | @bind-Value="@Date" | Component ↔ State sync |
| Dynamic | @bind-Value + events | Reactive updates with side effects |
Key Properties
- Value - Selected date (get/set)
- Min - Earliest selectable date (DateTime, inclusive)
- Max - Latest selectable date (DateTime, inclusive)
- TValue - Type parameter for binding:
DateTime,DateTime?, orDateOnly(.NET 6+)
---
One-Way Binding
What is One-Way Binding?
Component displays a value passed from parent, but changes don't automatically update the parent.
Syntax
<SfCalendar TValue="DateTime?" Value="@SelectedDate"></SfCalendar>When to Use
- Display calendar with pre-selected date
- User selections don't need immediate parent update
- Parent updates calendar value manually (button click, etc.)
Example
@using Syncfusion.Blazor.Calendars
<h3>One-Way Binding Demo</h3>
<p>Selected: @SelectedDate?.ToString("dd/MM/yyyy")</p>
<SfCalendar TValue="DateTime?" Value="@SelectedDate"></SfCalendar>
<button @onclick="UpdateDate">Set to Today</button>
@code {
public DateTime? SelectedDate { get; set; } = new DateTime(2024, 3, 15);
private void UpdateDate()
{
SelectedDate = DateTime.Now;
}
}Behavior: 1. Calendar shows March 15, 2024 2. User clicks a date in calendar (no visible change to display) 3. Button click updates SelectedDate, calendar re-renders with new date
Important Notes
- Calendar value changes via UI don't update
SelectedDateautomatically - To sync changes, use two-way binding (
@bind-Value) or events (ValueChange) - Parent must manually trigger re-renders or update state
---
Two-Way Binding
What is Two-Way Binding?
Component and parent stay in perfect sync. User selects date → calendar updates. Parent updates date → calendar re-renders automatically.
Syntax
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate"></SfCalendar>The @bind- prefix establishes two-way binding.
When to Use
- Calendar selection should immediately update parent state
- Display other UI based on selected date
- Share selected date between multiple components
- Form submission includes selected calendar date
Example 1: Basic Two-Way Binding
@using Syncfusion.Blazor.Calendars
<h3>Two-Way Binding Demo</h3>
<p>You selected: @SelectedDate?.ToString("dddd, dd MMMM yyyy")</p>
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate"></SfCalendar>
<button @onclick="ResetToToday">Reset</button>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
private void ResetToToday()
{
SelectedDate = DateTime.Now;
}
}Behavior: 1. Calendar displays current date 2. User clicks a date → text updates immediately 3. Reset button updates SelectedDate → calendar re-renders
Example 2: Reactive Display Based on Selection
@using Syncfusion.Blazor.Calendars
<h3>Event Timeline</h3>
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate"></SfCalendar>
<div class="event-details">
<h4>Events for @SelectedDate?.ToString("dd/MM/yyyy"):</h4>
@if (GetEventsForDate(SelectedDate).Count > 0)
{
<ul>
@foreach (var evt in GetEventsForDate(SelectedDate))
{
<li>@evt</li>
}
</ul>
}
else
{
<p>No events scheduled.</p>
}
</div>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
private Dictionary<DateTime, List<string>> Events = new()
{
{ DateTime.Now, new() { "Team Meeting", "Lunch" } },
{ DateTime.Now.AddDays(1), new() { "Project Deadline" } },
{ DateTime.Now.AddDays(7), new() { "Conference" } }
};
private List<string> GetEventsForDate(DateTime? date)
{
if (date == null) return new();
var dateOnly = date.Value.Date;
return Events.ContainsKey(dateOnly) ? Events[dateOnly] : new();
}
}Output: Calendar shows, and selecting a date displays associated events.
Example 3: Form with Calendar Field
@using Syncfusion.Blazor.Calendars
<h3>Appointment Booking</h3>
<EditForm Model="@Appointment" OnValidSubmit="@HandleSubmit">
<div>
<label>Select Appointment Date:</label>
<SfCalendar TValue="DateTime?" @bind-Value="@Appointment.Date"></SfCalendar>
</div>
<p>Date: @Appointment.Date?.ToString("dd/MM/yyyy")</p>
<button type="submit">Book Appointment</button>
</EditForm>
@code {
public class AppointmentModel
{
public DateTime? Date { get; set; }
}
private AppointmentModel Appointment = new();
private async Task HandleSubmit()
{
// Submit appointment with selected date
Console.WriteLine($"Booking appointment for {Appointment.Date}");
}
}Output: Calendar integrated in a form; selected date included in submission.
---
DateOnly Support
What is DateOnly?
DateOnly (.NET 6+) represents a date without time component, more efficient than DateTime?.
When to Use DateOnly
- Time component is irrelevant
- Reduces memory footprint
- Cleaner semantics (date ≠ date+time)
- .NET 6+ target framework required
Syntax
<SfCalendar TValue="DateOnly" @bind-Value="@SelectedDate"></SfCalendar>
@code {
public DateOnly SelectedDate { get; set; } = DateOnly.FromDateTime(DateTime.Now);
}Example 1: Simple DateOnly
@using Syncfusion.Blazor.Calendars
<h3>Birthday Selector (DateOnly)</h3>
<p>Your birthday: @SelectedDate</p>
<SfCalendar TValue="DateOnly" @bind-Value="@SelectedDate"></SfCalendar>
@code {
public DateOnly SelectedDate { get; set; } = DateOnly.FromDateTime(DateTime.Now);
}Example 2: DateOnly with Min/Max
@using Syncfusion.Blazor.Calendars
<h3>Meeting Room Booking (18-60 days out)</h3>
<SfCalendar TValue="DateOnly"
@bind-Value="@BookingDate"
Min="@MinDate"
Max="@MaxDate">
</SfCalendar>
<p>Booking: @BookingDate</p>
@code {
public DateOnly BookingDate { get; set; } = DateOnly.FromDateTime(DateTime.Now);
public DateOnly MinDate { get; set; } = DateOnly.FromDateTime(DateTime.Now.AddDays(18));
public DateOnly MaxDate { get; set; } = DateOnly.FromDateTime(DateTime.Now.AddDays(60));
}DateOnly vs DateTime?
| Aspect | DateOnly | DateTime? |
|---|---|---|
| Memory | 4 bytes | 8 bytes |
| Time | Not stored | Includes time |
| Use | Date-only logic | Date+time needed |
| Min .NET | 6.0+ | Any |
| Semantics | Clearer intent | Generic |
---
Dynamic Value Changes
What is Dynamic Binding?
Update calendar value programmatically and have it reflect in the UI.
Challenge: Blazor State Management
When you change a property in code, Blazor doesn't automatically re-render unless: 1. Change happens in event handler 2. You call StateHasChanged()
Solution: Use Events
Handle ValueChange event to detect selection and update state:
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" ValueChange="@OnDateChanged"></CalendarEvents>
</SfCalendar>
@code {
private void OnDateChanged(ChangedEventArgs<DateTime?> args)
{
// args.Value contains new date
// Update state here
StateHasChanged(); // Optional - usually implicit
}
}Example 1: Programmatic Updates
@using Syncfusion.Blazor.Calendars
<h3>Calendar with Programmatic Control</h3>
<div>
<button @onclick="GoToToday">Go to Today</button>
<button @onclick="GoToNextMonth">Next Month</button>
<button @onclick="GoToPreviousMonth">Previous Month</button>
</div>
<p>Selected: @SelectedDate?.ToString("dd/MM/yyyy")</p>
<SfCalendar TValue="DateTime?"
@bind-Value="@SelectedDate"
Min="@MinDate"
Max="@MaxDate">
</SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
public DateTime MinDate { get; set; } = DateTime.Now.AddMonths(-12);
public DateTime MaxDate { get; set; } = DateTime.Now.AddMonths(12);
private void GoToToday()
{
SelectedDate = DateTime.Now;
}
private void GoToNextMonth()
{
if (SelectedDate.HasValue)
{
var next = SelectedDate.Value.AddMonths(1);
if (next <= MaxDate)
SelectedDate = next;
}
}
private void GoToPreviousMonth()
{
if (SelectedDate.HasValue)
{
var prev = SelectedDate.Value.AddMonths(-1);
if (prev >= MinDate)
SelectedDate = prev;
}
}
}Example 2: Cascading Date Selection
@using Syncfusion.Blazor.Calendars
<h3>Cascading Selection</h3>
<div class="row">
<div class="col">
<h5>Start Date:</h5>
<SfCalendar TValue="DateTime?"
@bind-Value="@StartDate"
Max="@EndDate">
</SfCalendar>
</div>
<div class="col">
<h5>End Date:</h5>
<SfCalendar TValue="DateTime?"
@bind-Value="@EndDate"
Min="@StartDate">
</SfCalendar>
</div>
</div>
<p>Duration: @((EndDate?.Date - StartDate?.Date)?.Days) days</p>
@code {
public DateTime? StartDate { get; set; } = DateTime.Now;
public DateTime? EndDate { get; set; } = DateTime.Now.AddDays(7);
}Behavior: Changing start date updates end date's minimum; vice versa.
---
Date Range Constraints
Purpose
Restrict date selection to valid boundaries using Min and Max.
Properties
- Min (DateTime) - Earliest selectable date (inclusive, non-null)
- Max (DateTime) - Latest selectable date (inclusive, non-null)
Behavior
- Dates outside [Min, Max] are disabled (grayed out)
- User cannot select disabled dates
- If
Valueis set outside range, it's auto-corrected to nearest boundary - Dates are compared by date only; time components ignored
Example 1: Business Days Only
@using Syncfusion.Blazor.Calendars
<h3>Book Meeting (Business Days Only)</h3>
<SfCalendar TValue="DateTime?"
@bind-Value="@BookingDate"
Min="@MonthStart"
Max="@MonthEnd">
</SfCalendar>
<p>Booking: @BookingDate?.ToString("dd/MM/yyyy")</p>
@code {
public DateTime? BookingDate { get; set; } = DateTime.Now;
public DateTime MonthStart { get; set; } = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
public DateTime MonthEnd { get; set; } = new DateTime(DateTime.Now.Year, DateTime.Now.Month,
DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month));
}Example 2: Past Dates Disabled
@using Syncfusion.Blazor.Calendars
<h3>No Past Dates (Today onwards)</h3>
<SfCalendar TValue="DateTime?"
@bind-Value="@SelectedDate"
Min="@minBookingDate">
</SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
private DateTime minBookingDate = DateTime.Now;
}Example 3: Future Dates Only (90 days window)
@using Syncfusion.Blazor.Calendars
<h3>Plan Trip (Next 90 Days)</h3>
<SfCalendar TValue="DateTime?"
@bind-Value="@TripDate"
Min="@minTripDate"
Max="@maxTripDate">
</SfCalendar>
<p>Trip Date: @TripDate?.ToString("dd/MM/yyyy")</p>
@code {
private DateTime minTripDate = DateTime.Now;
private DateTime maxTripDate = DateTime.Now.AddDays(90);
public DateTime? TripDate { get; set; } = DateTime.Now.AddDays(14);
}---
Common Patterns
Pattern 1: Read-Only Display
<SfCalendar TValue="DateTime?" Value="@DisplayDate" Enabled="false"></SfCalendar>Pattern 2: Today Pre-selected
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate"></SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
}Pattern 3: Reset to Default
<button @onclick="ResetDate">Clear Selection</button>
@code {
private void ResetDate() => SelectedDate = null;
}Pattern 4: Future Dates + Range Validation
<SfCalendar TValue="DateTime?"
@bind-Value="@SelectedDate"
Min="@minAllowedDate"
Max="@maxAllowedDate">
</SfCalendar>
@code {
private DateTime minAllowedDate = DateTime.Now;
private DateTime maxAllowedDate = DateTime.Now.AddDays(365);
}Pattern 5: Exact Date Match
@if (SelectedDate == new DateTime(2024, 12, 25))
{
<p>You selected Christmas!</p>
}---
Type Mismatch Troubleshooting
Issue: "Cannot bind to property of type X"
Common Cause: TValue doesn't match property type.
Wrong:
<SfCalendar TValue="DateTime" @bind-Value="@SelectedDate"></SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } // Nullable, but TValue is not
}Fix:
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate"></SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } // Matches TValue
}Issue: DateTime vs DateOnly Mismatch
Wrong:
<SfCalendar TValue="DateOnly" @bind-Value="@SelectedDate"></SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } // Should be DateOnly
}Fix:
<SfCalendar TValue="DateOnly" @bind-Value="@SelectedDate"></SfCalendar>
@code {
public DateOnly SelectedDate { get; set; } = DateOnly.FromDateTime(DateTime.Now);
}Events & Interactions
Table of Contents
- Available Events
- ValueChange Event
- OnRenderDayCell Event
- Lifecycle Events
- Navigated Event
- Common Patterns
- Event Examples
---
Available Events
The Blazor Calendar fires events during user interaction and component lifecycle:
| Event | Trigger | Purpose |
|---|---|---|
| ValueChange | Date selected | Detect date selection change |
| OnRenderDayCell | Each day cell renders | Customize cell appearance |
| Created | Component initialized | Post-render setup |
| Destroyed | Component disposed | Cleanup resources |
| Navigated | User navigates views | Track view changes |
Event Declaration Pattern
All calendar events use <CalendarEvents> child element:
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?">
<!-- Event handlers here -->
</CalendarEvents>
</SfCalendar>---
ValueChange Event
Purpose
Triggered when the user selects a new date in the calendar.
When to Use
- React to date selection (update UI, fetch data)
- Validate selected date
- Update related calendars or UI elements
- Track user interactions for analytics
Syntax
<CalendarEvents TValue="DateTime?" ValueChange="@OnDateChanged"></CalendarEvents>Event Args
public class ChangedEventArgs<T>
{
public T Value { get; set; } // New selected date
public T PreviousValue { get; set; } // Previous selection
}Example 1: Basic Date Selection Tracking
@using Syncfusion.Blazor.Calendars
<h3>Date Selection Tracker</h3>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" ValueChange="@OnDateChanged"></CalendarEvents>
</SfCalendar>
<p>Last selected: @LastSelected?.ToString("dd/MM/yyyy")</p>
@code {
public DateTime? LastSelected { get; set; }
private void OnDateChanged(ChangedEventArgs<DateTime?> args)
{
LastSelected = args.Value;
}
}Example 2: Validate Date Range
@using Syncfusion.Blazor.Calendars
<h3>Appointment Booking (Weekdays Only)</h3>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" ValueChange="@ValidateWeekday"></CalendarEvents>
</SfCalendar>
<p>Status: @StatusMessage</p>
@code {
public DateTime? SelectedDate { get; set; }
public string StatusMessage { get; set; } = "Select a weekday";
private void ValidateWeekday(ChangedEventArgs<DateTime?> args)
{
if (args.Value == null)
{
StatusMessage = "No date selected";
return;
}
var dayOfWeek = args.Value.Value.DayOfWeek;
if (dayOfWeek == DayOfWeek.Saturday || dayOfWeek == DayOfWeek.Sunday)
{
StatusMessage = "❌ Weekends not available";
// Could reset value here
}
else
{
StatusMessage = $"✓ Appointment booked for {args.Value:dddd, dd MMMM}";
SelectedDate = args.Value;
}
}
}Example 3: Cascade Updates
@using Syncfusion.Blazor.Calendars
<h3>Trip Planning - Date Changes Cascade</h3>
<div>
<h5>Start Date:</h5>
<SfCalendar TValue="DateTime?" @bind-Value="@StartDate">
<CalendarEvents TValue="DateTime?" ValueChange="@OnStartDateChanged"></CalendarEvents>
</SfCalendar>
<h5>End Date:</h5>
<SfCalendar TValue="DateTime?" @bind-Value="@EndDate" Min="@StartDate"></SfCalendar>
</div>
<p>Duration: @CalculateDuration() days</p>
@code {
public DateTime? StartDate { get; set; } = DateTime.Now;
public DateTime? EndDate { get; set; } = DateTime.Now.AddDays(7);
private void OnStartDateChanged(ChangedEventArgs<DateTime?> args)
{
StartDate = args.Value;
// Auto-adjust end date if before new start
if (EndDate < StartDate)
{
EndDate = StartDate?.AddDays(7);
}
}
private int CalculateDuration()
{
return StartDate == null || EndDate == null
? 0
: (EndDate.Value.Date - StartDate.Value.Date).Days;
}
}---
OnRenderDayCell Event
Purpose
Triggered for each day cell as it renders. Allows customization of cell appearance, content, or state.
When to Use
- Highlight special dates (holidays, events)
- Disable specific dates (blackout dates)
- Add custom styling or icons to dates
- Show tooltips or additional info
- Mark booked/available dates
Syntax
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@CustomizeCell"></CalendarEvents>Event Args
public class RenderDayCellEventArgs
{
public DateTime Date { get; set; } // Date of the cell
public string CellTemplate { get; set; } // HTML to render
public bool IsDisabled { get; set; } // Disable cell
public bool IsOutOfRange { get; set; } // Out of Min/Max range
public List<string> ClassList { get; set; } // CSS classes to apply
}Example 1: Highlight Weekends
@using Syncfusion.Blazor.Calendars
<h3>Calendar with Weekend Highlighting</h3>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@HighlightWeekends"></CalendarEvents>
</SfCalendar>
<style>
.weekend { background-color: #ffe6e6; }
</style>
@code {
private void HighlightWeekends(RenderDayCellEventArgs args)
{
if (args.Date.DayOfWeek == DayOfWeek.Saturday ||
args.Date.DayOfWeek == DayOfWeek.Sunday)
{
args.ClassList.Add("weekend");
}
}
}Example 2: Disable Past Dates
@using Syncfusion.Blazor.Calendars
<h3>No Past Dates (Custom Rendering)</h3>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@DisablePastDates"></CalendarEvents>
</SfCalendar>
@code {
private void DisablePastDates(RenderDayCellEventArgs args)
{
if (args.Date.Date < DateTime.Now.Date)
{
args.IsDisabled = true;
}
}
}Example 3: Mark Special Dates with Icons
@using Syncfusion.Blazor.Calendars
<h3>Event Calendar</h3>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@MarkSpecialDates"></CalendarEvents>
</SfCalendar>
<style>
.has-event::after {
content: "•";
color: red;
font-size: 20px;
position: absolute;
bottom: 0;
}
.birthday::after {
content: "🎂";
font-size: 12px;
position: absolute;
top: 2px;
right: 2px;
}
</style>
@code {
private HashSet<int> EventDates = new() { 5, 12, 20, 25 };
private HashSet<int> BirthdayDates = new() { 15, 28 };
private void MarkSpecialDates(RenderDayCellEventArgs args)
{
if (EventDates.Contains(args.Date.Day))
{
args.ClassList.Add("has-event");
}
if (BirthdayDates.Contains(args.Date.Day))
{
args.ClassList.Add("birthday");
}
}
}Example 4: Disable Booked Slots
@using Syncfusion.Blazor.Calendars
<h3>Meeting Room Booking</h3>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@MarkBookedDates"></CalendarEvents>
</SfCalendar>
<style>
.booked { background-color: #cccccc; opacity: 0.6; }
</style>
@code {
private HashSet<int> BookedDates = new() { 3, 7, 14, 21, 28 };
private void MarkBookedDates(RenderDayCellEventArgs args)
{
if (BookedDates.Contains(args.Date.Day))
{
args.IsDisabled = true;
args.ClassList.Add("booked");
}
}
}Example 5: Today & Selected Date Styling
@using Syncfusion.Blazor.Calendars
<h3>Date Styling</h3>
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate">
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@StyleDates"></CalendarEvents>
</SfCalendar>
<style>
.today-marker { border: 3px solid blue; }
.selected-marker { background-color: #e3f2fd; }
</style>
@code {
public DateTime? SelectedDate { get; set; }
private void StyleDates(RenderDayCellEventArgs args)
{
if (args.Date.Date == DateTime.Now.Date)
{
args.ClassList.Add("today-marker");
}
if (SelectedDate != null && args.Date.Date == SelectedDate.Value.Date)
{
args.ClassList.Add("selected-marker");
}
}
}---
Lifecycle Events
Created Event
Triggered after the Calendar component initializes and renders.
<CalendarEvents TValue="DateTime?" Created="@OnCreated"></CalendarEvents>
@code {
private void OnCreated(object args)
{
// Component ready
Console.WriteLine("Calendar initialized");
}
}Destroyed Event
Triggered when the Calendar is disposed (component removed from DOM).
<CalendarEvents TValue="DateTime?" Destroyed="@OnDestroyed"></CalendarEvents>
@code {
private void OnDestroyed(object args)
{
// Cleanup
Console.WriteLine("Calendar disposed");
}
}Example: Track Component Lifecycle
@using Syncfusion.Blazor.Calendars
<h3>Lifecycle Tracking</h3>
@if (ShowCalendar)
{
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?"
Created="@OnCreated"
Destroyed="@OnDestroyed">
</CalendarEvents>
</SfCalendar>
}
<p>Status: @LifecycleStatus</p>
<button @onclick="ToggleCalendar">@(ShowCalendar ? "Hide" : "Show") Calendar</button>
@code {
public bool ShowCalendar { get; set; } = true;
public string LifecycleStatus { get; set; } = "Calendar hidden";
private void OnCreated(object args)
{
LifecycleStatus = "Calendar created at " + DateTime.Now.ToLongTimeString();
}
private void OnDestroyed(object args)
{
LifecycleStatus = "Calendar destroyed at " + DateTime.Now.ToLongTimeString();
}
private void ToggleCalendar()
{
ShowCalendar = !ShowCalendar;
}
}---
Navigated Event
Purpose
Triggered when user navigates between views (Month ↔ Year ↔ Decade) or when the displayed month/year changes.
When to Use
- Track user navigation for analytics
- Update dependent UI (breadcrumb, title)
- Control navigation behavior
- Fetch data for displayed period
Syntax
<CalendarEvents TValue="DateTime?" Navigated="@OnNavigated"></CalendarEvents>Event Args
public class NavigatedEventArgs
{
public DateTime Date { get; set; } // Current focus date
public CalendarView View { get; set; } // Current view (Month/Year/Decade)
}Example
@using Syncfusion.Blazor.Calendars
<h3>Navigation Tracking</h3>
<p>Current View: @CurrentView</p>
<p>Viewing: @CurrentPeriod</p>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" Navigated="@OnNavigated"></CalendarEvents>
</SfCalendar>
@code {
public string CurrentView { get; set; } = "Month";
public string CurrentPeriod { get; set; } = DateTime.Now.ToString("MMMM yyyy");
private void OnNavigated(NavigatedEventArgs args)
{
CurrentView = args.View.ToString();
CurrentPeriod = args.View == CalendarView.Month
? args.Date.ToString("MMMM yyyy")
: args.View == CalendarView.Year
? args.Date.ToString("yyyy")
: $"{args.Date.Year / 10 * 10}-{args.Date.Year / 10 * 10 + 9}";
}
}---
Common Patterns
Pattern 1: Validation + Feedback
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?" ValueChange="@ValidateAndFeedback"></CalendarEvents>
</SfCalendar>
@code {
private void ValidateAndFeedback(ChangedEventArgs<DateTime?> args)
{
// Validate
// Show feedback
// Update state
}
}Pattern 2: Multi-Event Handling
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?"
ValueChange="@OnDateChanged"
OnRenderDayCell="@OnCellRender"
Navigated="@OnNavigated">
</CalendarEvents>
</SfCalendar>Pattern 3: Conditional Cell Customization
<CalendarEvents TValue="DateTime?" OnRenderDayCell="@CustomizeCell"></CalendarEvents>
@code {
private void CustomizeCell(RenderDayCellEventArgs args)
{
if (IsHoliday(args.Date))
args.ClassList.Add("holiday");
if (IsWeekend(args.Date))
args.ClassList.Add("weekend");
if (IsBooked(args.Date))
args.IsDisabled = true;
}
private bool IsHoliday(DateTime date) => /* logic */;
private bool IsWeekend(DateTime date) => /* logic */;
private bool IsBooked(DateTime date) => /* logic */;
}---
Event Examples
Complete Booking Calendar
@using Syncfusion.Blazor.Calendars
<h3>Restaurant Reservation System</h3>
<div class="booking-form">
<h5>Select Date:</h5>
<SfCalendar TValue="DateTime?">
<CalendarEvents TValue="DateTime?"
ValueChange="@OnDateSelected"
OnRenderDayCell="@HighlightAvailable">
</CalendarEvents>
</SfCalendar>
<div class="booking-info">
<p>Selected: @SelectedDate?.ToString("dddd, dd MMMM yyyy")</p>
<p>Status: @BookingStatus</p>
<p>Available Slots: @AvailableSlots</p>
</div>
</div>
<style>
.available { background-color: #c8e6c9; }
.booked { background-color: #ffcccc; }
</style>
@code {
public DateTime? SelectedDate { get; set; }
public string BookingStatus { get; set; } = "Select a date";
public int AvailableSlots { get; set; } = 0;
private Dictionary<int, int> AvailabilityMap = new()
{
{ 1, 5 }, { 5, 2 }, { 10, 8 }, { 15, 0 }, { 20, 3 }, { 25, 6 }
};
private void OnDateSelected(ChangedEventArgs<DateTime?> args)
{
SelectedDate = args.Value;
if (SelectedDate != null)
{
int day = SelectedDate.Value.Day;
AvailableSlots = AvailabilityMap.ContainsKey(day)
? AvailabilityMap[day]
: 7;
BookingStatus = AvailableSlots > 0
? $"✓ {AvailableSlots} slots available"
: "❌ Fully booked";
}
}
private void HighlightAvailable(RenderDayCellEventArgs args)
{
int day = args.Date.Day;
if (AvailabilityMap.ContainsKey(day))
{
if (AvailabilityMap[day] == 0)
{
args.IsDisabled = true;
args.ClassList.Add("booked");
}
else
{
args.ClassList.Add("available");
}
}
}
}---
Debugging Events
Enable Console Logging
private void OnDateChanged(ChangedEventArgs<DateTime?> args)
{
Console.WriteLine($"Date changed from {args.PreviousValue} to {args.Value}");
}Check Event Firing
Add debug output to verify event handlers are called:
private void OnRenderDayCell(RenderDayCellEventArgs args)
{
if (args.Date.Day == 1)
Console.WriteLine($"Rendering day 1");
}Localization & Globalization
Table of Contents
- Locale Support
- Right-to-Left (RTL) Layout
- Islamic Calendar
- Week Customization
- Date Formatting
- Common Patterns
---
Locale Support
What is Localization?
Localization adapts the Calendar to different languages and cultures:
- Month/day names in different languages
- Date formats (DD/MM/YYYY vs MM/DD/YYYY)
- Week numbering and first day of week
- Number formatting
Supported Locales
Syncfusion Calendar supports 150+ locales including:
- English (en)
- Spanish (es)
- French (fr)
- German (de)
- Chinese (zh)
- Japanese (ja)
- Arabic (ar)
- And many more...
Common Locale Codes
| Language | Code | Region | Example |
|---|---|---|---|
| English | en | United States | en-US |
| Spanish | es | Spain | es-ES |
| French | fr | France | fr-FR |
| German | de | Germany | de-DE |
| Italian | it | Italy | it-IT |
| Chinese | zh | China | zh-CN |
| Japanese | ja | Japan | ja-JP |
| Korean | ko | Korea | ko-KR |
| Arabic | ar | Saudi Arabia | ar-SA |
| Russian | ru | Russia | ru-RU |
| Portuguese | pt | Brazil | pt-BR |
Right-to-Left (RTL) Layout
What is RTL?
Right-to-Left layout is required for languages like Arabic, Hebrew, Persian, and Urdu where text flows from right to left.
Enabling RTL
<SfCalendar TValue="DateTime?" EnableRtl="true"></SfCalendar>Property
- EnableRtl (bool) - Enables/disables RTL layout
Important Notes
- RTL is not automatically inferred from Locale
- Must explicitly set
EnableRtl="true"for RTL languages - Even if you set arabic culture, RTL won't activate without
EnableRtl="true"
---
Islamic Calendar
What is Islamic Calendar?
Islamic Calendar (Hijri) is the lunar calendar used in Muslim cultures. Dates are approximately 11 days behind the Gregorian calendar.
Using Islamic Calendar
The Calendar can display Islamic dates alongside Gregorian dates.
@using Syncfusion.Blazor.Calendars
<h3>Islamic Calendar View</h3>
<SfCalendar TValue="DateTime?" EnableRtl="true"></SfCalendar>Example: Dual Calendar Display
@using Syncfusion.Blazor.Calendars
<h3>Gregorian & Islamic Calendar</h3>
<div class="calendar-row">
<div class="calendar-col">
<h5>Gregorian Calendar</h5>
<SfCalendar TValue="DateTime?"
@bind-Value="@SelectedDate"
EnableRtl="false">
</SfCalendar>
</div>
<div class="calendar-col">
<h5>Islamic Calendar (Hijri)</h5>
<SfCalendar TValue="DateTime?"
@bind-Value="@SelectedDate"
EnableRtl="true">
</SfCalendar>
</div>
</div>
<p>Selected: @SelectedDate?.ToString("dd/MM/yyyy")</p>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
}
<style>
.calendar-row {
display: flex;
gap: 20px;
}
.calendar-col {
flex: 1;
}
</style>Islamic Date Conversion Notes
- Hijri year ~354 days (lunar), Gregorian ~365 days (solar)
- Hijri year approximately 11 days shorter than Gregorian
- Year 1 AH = July 16, 622 CE (Islamic era start)
- Most Islamic calendars are also RTL
---
Week Customization
First Day of Week
By default, Sunday is the first day of the week (0). Different cultures use different first days:
| Day | Code |
|---|---|
| Sunday | 0 |
| Monday | 1 |
| Tuesday | 2 |
| Wednesday | 3 |
| Thursday | 4 |
| Friday | 5 |
| Saturday | 6 |
Setting First Day
<SfCalendar TValue="DateTime?" FirstDayOfWeek="1"></SfCalendar>Example 1: Monday-First Calendar
@using Syncfusion.Blazor.Calendars
<h3>Week Starts on Monday</h3>
<SfCalendar TValue="DateTime?" FirstDayOfWeek="1"></SfCalendar>Output: Calendar shows Mon-Sun instead of Sun-Sat.
Example 3: Show Week Numbers
@using Syncfusion.Blazor.Calendars
<h3>Calendar with ISO Week Numbers</h3>
<SfCalendar TValue="DateTime?" ShowWeekNumbers="true"></SfCalendar>Output: Shows week numbers in the left column (ISO 8601 standard).
---
Date Formatting
Locale-Based Date Formats
Different locales use different date formats:
| Locale | Format | Example |
|---|---|---|
| en-US | MM/DD/YYYY | 03/19/2024 |
| en-GB | DD/MM/YYYY | 19/03/2024 |
| de-DE | DD.MM.YYYY | 19.03.2024 |
| fr-FR | DD/MM/YYYY | 19/03/2024 |
| ja-JP | YYYY/MM/DD | 2024/03/19 |
Displaying Formatted Dates
@using Syncfusion.Blazor.Calendars
<h3>Locale-Aware Date Display</h3>
<p>@SelectedDate?.ToString("d", System.Globalization.CultureInfo.GetCultureInfo(CurrentLocale))</p>
<SfCalendar TValue="DateTime?"
@bind-Value="@SelectedDate">
</SfCalendar>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
}Custom Date Formatting
@using Syncfusion.Blazor.Calendars
<h3>Custom Date Format</h3>
<SfCalendar TValue="DateTime?" @bind-Value="@SelectedDate"></SfCalendar>
<p>ISO Format: @SelectedDate?.ToString("O")</p>
<p>Long Format: @SelectedDate?.ToString("D")</p>
<p>Short Format: @SelectedDate?.ToString("d")</p>
@code {
public DateTime? SelectedDate { get; set; } = DateTime.Now;
}---
Common Patterns
Pattern 1: Auto-Detect System Locale
@code {
private string SystemLocale { get; set; } =
System.Globalization.CultureInfo.CurrentCulture.Name;
private bool SystemIsRtl { get; set; } =
System.Globalization.CultureInfo.CurrentCulture.TextInfo.IsRightToLeft;
}Pattern 2: Time Zone-Aware Calendar
@code {
private DateTime GetLocalDateTime(DateTime utc)
{
var tz = TimeZoneInfo.FindSystemTimeZoneById("Asia/Tokyo");
return TimeZoneInfo.ConvertTime(utc, tz);
}
private DateTime ConvertToUtc(DateTime local)
{
var tz = TimeZoneInfo.FindSystemTimeZoneById("Asia/Tokyo");
return TimeZoneInfo.ConvertTimeToUtc(local, tz);
}
}Pattern 4: Multi-Calendar View
@using Syncfusion.Blazor.Calendars
<h3>Calendar Comparison</h3>
<div class="calendars-grid">
<div>
<h5>US Format</h5>
<SfCalendar TValue="DateTime?" FirstDayOfWeek="0"></SfCalendar>
</div>
<div>
<h5>European Format</h5>
<SfCalendar TValue="DateTime?" FirstDayOfWeek="1"></SfCalendar>
</div>
<div>
<h5>Islamic Calendar</h5>
<SfCalendar TValue="DateTime?" EnableRtl="true"></SfCalendar>
</div>
</div>
<style>
.calendars-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
</style>---
Locale Data Loading
Setting Up Locale Files
Syncfusion provides locale JSON files. For custom locales:
1. Get locale file from Syncfusion resources 2. Place in wwwroot/locale/ folder 3. Load via HTTP client 4. Register with component
---
Best Practices
1. Always set locale explicitly - Don't rely on browser defaults 2. Load locale data early - Prevent flickering 3. Test with actual locales - Different date formats, week starts 4. Use locale-appropriate defaults - First day of week, date format 5. Consider RTL - Test with Arabic, Hebrew, Persian 6. Handle timezone differences - Store as UTC, display in user timezone 7. Test accessibility - Ensure locale changes don't break keyboard nav