Implementing Syncfusion Angular Calendars
Calendars
A comprehensive guide for implementing the Syncfusion Essential JS 2 Calendar component in Angular applications. Learn to create date pickers, manage calendar views, handle events, and customize styling.
Calendar Overview
The Syncfusion Angular Calendar component is a date selection widget that provides:
- Multiple calendar views: Month (default), Year, and Decade views with smooth navigation
- Date selection modes: Single date or multiple dates with
isMultiSelectionproperty - Navigation control:
navigateTo()method for programmatic view switching - Date manipulation methods:
addDate()andremoveDate()for multi-selection management - Comprehensive event system: change, created, navigated, renderDayCell, destroyed events
- Localization support: Locale-specific formatting, day header formats, first day of week
- Accessibility: Full WCAG 2.2 compliance, keyboard navigation, RTL support
- Rich customization: CSS classes, custom rendering, day cell customization
- Persistence: Optional state persistence across page reloads
Package: @syncfusion/ej2-angular-calendars
Documentation Navigation
Read the following references based on your specific needs:
Getting Started
📄 Read: references/getting-started.md
- Package installation and module setup
- CSS theme imports and dependencies
- Basic calendar implementation
- Component initialization in Angular
- Running and testing setup
Calendar Views
📄 Read: references/calendar-views.md
- Month view (default display)
- Year view implementation
- Decade view implementation
- View navigation and transitions
startproperty usagedepthproperty for restricting views
Date Selection
📄 Read: references/date-selection.md
- Single date selection
- Multiple date selection (
isMultiSelection) valueproperty for single datesvaluesarray for multiple dates- Min/max date constraints
- Date range validation
Events & Methods
📄 Read: references/events-and-methods.md
- Event handlers (change, created, navigated, renderDayCell, destroyed)
addDate()method for multi-selectionremoveDate()method for multi-selectionnavigateTo()for programmatic navigationcurrentView()to get active viewgetPersistData()to retrieve persistence datadestroy()to destroy the calendar widget- RenderDayCell for custom day styling
Calendar Navigation
📄 Read: references/calendar-navigation.md
- Month navigation controls
- Year and Decade view switching
- Today button (
showTodayButton) firstDayOfWeekproperty- Week number display (
weekNumber) - Keyboard shortcuts and navigation
Accessibility & Globalization
📄 Read: references/accessibility-and-globalization.md
- WCAG 2.2 and Section 508 compliance
- WAI-ARIA attributes and roles
- Keyboard navigation (arrows, enter, spacebar)
- Screen reader compatibility
- Localization (locale property)
- Day header formats (Short, Narrow, Abbreviated, Wide)
- RTL (Right-to-Left) support
Styling & Customization
📄 Read: references/styling-and-customization.md
- CSS class customization (.e-calendar, .e-day-cell, .e-selected)
- Theme selection (Material, Bootstrap, Tailwind, Fabric)
- Dark mode implementation
- Custom day cell styling via renderDayCell
- Disabled dates styling
- Hover and focus states
API Reference
📄 Read: references/api-reference.md
- Complete property reference (value, values, isMultiSelection, min, max, start, depth, showTodayButton, locale, dayHeaderFormat, weekNumber, weekRule, firstDayOfWeek, cssClass, enableRtl, enabled, calendarMode, keyConfigs, enablePersistence, serverTimezoneOffset)
- All method signatures with examples (addDate, removeDate, navigateTo, currentView, getPersistData, destroy)
- Event argument types (ChangedEventArgs, NavigatedEventArgs, RenderDayCellEventArgs)
- Key configurations for keyboard shortcuts
- Calendar modes (Gregorian, Islamic)
- Return types and descriptions
Quick Start Example
// app.component.ts
import { Component } from '@angular/core';
import { ChangedEventArgs } from '@syncfusion/ej2-calendars';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Single date selection
selectedDate: Date = new Date();
// Multiple date selection
selectedDates: Date[] = [
new Date(2026, 2, 15),
new Date(2026, 2, 20),
new Date(2026, 2, 25)
];
// Calendar configuration
minDate: Date = new Date(2020, 0, 1);
maxDate: Date = new Date(2030, 11, 31);
// Event handler
onCalendarChange(args: ChangedEventArgs): void {
console.log('Selected date:', args.value);
}
}
<!-- app.component.html -->
<div style="padding: 20px; font-family: Arial, sans-serif;">
<h2>Single Date Selection</h2>
<ejs-calendar
[(ngModel)]="selectedDate"
[min]="minDate"
[max]="maxDate"
(change)="onCalendarChange($event)">
</ejs-calendar>
<p>Selected: {{ selectedDate | date:'medium' }}</p>
<h2>Multiple Date Selection</h2>
<ejs-calendar
[(ngModel)]="selectedDates"
[isMultiSelection]="true"
[showTodayButton]="true">
</ejs-calendar>
<p>Selected dates: {{ selectedDates.length }} dates</p>
</div>
/* app.component.css */
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-calendars/styles/material3.css';
:host ::ng-deep .e-calendar {
margin: 20px 0;
}
:host ::ng-deep .e-selected {
background-color: #3f51b5;
color: white;
}
Common Patterns
Pattern 1: Custom Date Range (Two Calendar Instances)
The Calendar component does not have built-in range selection. Use two separate Calendar instances with min/max constraints and the change event to implement a custom date range picker:
export class AppComponent {
startDate: Date = new Date();
endDate: Date = new Date();
onStartDateChange(args: ChangedEventArgs): void {
this.startDate = args.value;
// Ensure end date is not before start date
if (this.endDate < this.startDate) {
this.endDate = this.startDate;
}
}
onEndDateChange(args: ChangedEventArgs): void {
this.endDate = args.value;
}
getDaysInRange(): number {
const timeDiff = this.endDate.getTime() - this.startDate.getTime();
return Math.ceil(timeDiff / (1000 * 3600 * 24)) + 1;
}
}
<!-- Two separate Calendar instances for range selection -->
<ejs-calendar [(ngModel)]="startDate" (change)="onStartDateChange($event)"></ejs-calendar>
<ejs-calendar [(ngModel)]="endDate" [min]="startDate" (change)="onEndDateChange($event)"></ejs-calendar>
Pattern 2: Calendar with Disabled Dates
Disable specific dates (weekends, holidays) using renderDayCell event:
export class AppComponent {
holidays: Date[] = [
new Date(2026, 11, 25), // Christmas
new Date(2026, 0, 1), // New Year
];
onRenderDayCell(args: RenderDayCellEventArgs): void {
// Disable weekends
if (args.date.getDay() === 0 || args.date.getDay() === 6) {
args.isDisabled = true;
}
// Disable holidays
if (this.isHoliday(args.date)) {
args.isDisabled = true;
}
}
private isHoliday(date: Date): boolean {
return this.holidays.some(holiday =>
holiday.toDateString() === date.toDateString()
);
}
}
Pattern 3: Multi-Selection with Add/Remove
Manage multiple selected dates programmatically:
export class AppComponent {
@ViewChild('calendar') calendarRef!: CalendarComponent;
selectedDates: Date[] = [];
addDateToSelection(date: Date): void {
// Check if already selected
if (!this.selectedDates.some(d =>
d.toDateString() === date.toDateString())) {
this.calendarRef.addDate(date);
}
}
removeDateFromSelection(date: Date): void {
this.calendarRef.removeDate(date);
}
clearAllDates(): void {
if (this.selectedDates.length > 0) {
this.calendarRef.removeDate(this.selectedDates);
}
}
}
Pattern 4: Year/Decade View Navigation
Implement navigation to different calendar views:
export class AppComponent {
@ViewChild('calendar') calendarRef!: CalendarComponent;
navigateToYear(year: number): void {
const dateInYear = new Date(year, 0, 1);
this.calendarRef.navigateTo('Year', dateInYear);
}
navigateToDecade(startYear: number): void {
const dateInDecade = new Date(startYear, 0, 1);
this.calendarRef.navigateTo('Decade', dateInDecade);
}
getCurrentView(): string {
return this.calendarRef.currentView();
}
}
Pattern 5: Reactive Form Integration
Integrate Calendar with Angular Reactive Forms:
export class AppComponent implements OnInit {
dateForm: FormGroup;
constructor(private fb: FormBuilder) {
this.dateForm = this.fb.group({
eventDate: [new Date(), Validators.required],
eventName: ['', Validators.required]
});
}
ngOnInit(): void {
// Subscribe to date changes
this.dateForm.get('eventDate')?.valueChanges.subscribe(date => {
console.log('Event date changed:', date);
});
}
submitForm(): void {
if (this.dateForm.valid) {
console.log('Form values:', this.dateForm.value);
}
}
}
<form [formGroup]="dateForm" (ngSubmit)="submitForm()">
<div>
<label for="eventDate">Event Date:</label>
<ejs-calendar
id="eventDate"
formControlName="eventDate">
</ejs-calendar>
</div>
<div>
<label for="eventName">Event Name:</label>
<input
id="eventName"
type="text"
formControlName="eventName">
</div>
<button type="submit" [disabled]="!dateForm.valid">Submit</button>
</form>
Key Props Reference
| Prop | Type | Description | Example |
|---|---|---|---|
value |
Date |
Single selected date | [value]="selectedDate" |
values |
Date[] |
Multiple selected dates | [values]="selectedDates" |
isMultiSelection |
boolean |
Enable multiple date selection | [isMultiSelection]="true" |
min |
Date |
Minimum selectable date | [min]="minDate" |
max |
Date |
Maximum selectable date | [max]="maxDate" |
start |
CalendarView |
Initial view (Month/Year/Decade) | start="Month" |
depth |
CalendarView |
Maximum view level | depth="Month" |
showTodayButton |
boolean |
Display today button | [showTodayButton]="true" |
locale |
string |
Culture/language code | locale="fr-FR" |
dayHeaderFormat |
DayHeaderFormats |
Day format (Short/Narrow/Abbreviated/Wide) | dayHeaderFormat="Abbreviated" |
weekNumber |
boolean |
Show week numbers | [weekNumber]="true" |
weekRule |
WeekRule |
Rule for first week of year (FirstDay/FirstFullWeek/FirstFourDayWeek) | weekRule="FirstFourDayWeek" |
firstDayOfWeek |
number |
First day (0=Sunday, 1=Monday) | [firstDayOfWeek]="1" |
cssClass |
string |
Custom CSS classes | cssClass="custom-calendar" |
enableRtl |
boolean |
Enable RTL layout | [enableRtl]="true" |
enabled |
boolean |
Enable/disable component | [enabled]="true" |
calendarMode |
CalendarType |
Calendar mode (Gregorian/Islamic) | calendarMode="Islamic" |
keyConfigs |
{ [key: string]: string } |
Custom keyboard shortcuts | [keyConfigs]="keyConfigs" |
enablePersistence |
boolean |
Persist state across page reloads | [enablePersistence]="true" |
serverTimezoneOffset |
number | null |
Server timezone offset for initial date processing | [serverTimezoneOffset]="330" |
Common Use Cases
Use Case 1: Event Booking System
- User selects start and end dates for event
- Disable past dates and weekends
- Solution: Combine min/max dates with renderDayCell for disable logic
- Reference: Calendar Views + Events & Methods
Use Case 2: Conference Schedule
- Display multiple highlighted dates (conference days)
- Allow year/decade navigation for planning
- Solution: Use isMultiSelection, highlight dates, navigate between views
- Reference: Date Selection + Calendar Navigation
Use Case 3: Accessible Booking Form
- Calendar integrated in form with keyboard navigation
- Screen reader compatible, WCAG 2.2 compliant
- Solution: Use Reactive Forms + Calendar events
- Reference: Accessibility & Globalization
Use Case 4: International Date Picker
- Support multiple languages and date formats
- Show RTL for Arabic, Hebrew
- Solution: Use locale property and localization
- Reference: Accessibility & Globalization
Use Case 5: Dynamic Date Constraints
- Disable dates based on business logic (availability, holidays)
- Update constraints based on user selections
- Solution: Use renderDayCell with dynamic logic
- Reference: Events & Methods + Calendar Views
DatePicker
The Syncfusion Angular DatePicker provides a user-friendly calendar interface for selecting individual dates with support for formatting, validation, date ranges, and complete accessibility (WCAG 2.2). This skill guides you through all essential implementation patterns and advanced features.
Component Overview
The DatePicker combines a text input with a popup calendar picker. Users can type dates directly or use the calendar to select. Key capabilities:
- Date selection via calendar UI or text input
- Multiple date formats (culture-aware, custom patterns)
- Date range validation (min/max, strict mode)
- Input masking for guided date entry
- Multiple calendar views (month → year → decade navigation)
- Accessibility (WCAG 2.2, ARIA, keyboard support, RTL)
- Internationalization (CLDR data, 100+ cultures)
- Form integration (FormValidator, reactive forms, template-driven forms)
Documentation and Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation and setup for Angular 21+ standalone architecture
- Package dependencies and imports
- Basic DatePicker implementation
- CSS theme imports
- Minimal working example
Date Formats and Parsing
📄 Read: references/date-formats-and-parsing.md
- Standard date format patterns (yyyy-MM-dd, dd/MM/yyyy, etc.)
- Culture-specific default formats
- Custom date format creation
- parseDate and formatDate methods
- Dynamic format switching
Date Range and Validation
📄 Read: references/date-range-and-validation.md
- Setting date range constraints (min/max properties)
- Out-of-range date handling and error states
- Null date validation and strictMode
- Invalid date detection
- Real-world date constraint patterns
Date Views and Navigation
📄 Read: references/date-views-and-navigation.md
- Start view configuration (month/year/decade)
- Depth view restrictions for limited selection
- Navigating between calendar views
- Month and year selection patterns
- Use cases for different view configurations
Masking and Editing
📄 Read: references/masking-and-editing.md
- Enabling date input masking for guided entry
- Mask patterns based on date format
- Keyboard navigation in masked input (up/down/left/right arrows)
- Custom mask placeholders
- Locale-aware mask placeholder text
Styling and Customization
📄 Read: references/styling-and-customization.md
- CSS customization for wrapper and input elements
- DatePicker icon styling and customization
- Full-screen mode on mobile devices
- Placeholder and readonly state customization
- Dark mode and Theme Studio integration
Accessibility and Forms
📄 Read: references/accessibility-and-forms.md
- WCAG 2.2 compliance and accessibility standards
- ARIA attributes (aria-expanded, aria-disabled, aria-activedescendant)
- Keyboard navigation support (arrow keys, Enter, Escape)
- Screen reader support and semantic markup
- FormValidator integration for date validation
- Reactive forms and template-driven forms patterns
- Custom validation rules
Globalization and Localization
📄 Read: references/globalization-and-localization.md
- CLDR data loading for culture-specific formatting
- Culture-aware date parsing and formatting
- Locale configuration and L10n setup
- First day of week by culture (week data)
- Right-to-Left (RTL) language support
- Multi-language examples
- Timezone-aware date handling
Testing & Quality Assurance
📄 Read: references/testing-guide.md
- Unit testing with Jasmine/Karma: parsing, validators, events
- E2E testing with Cypress: calendar interactions, form flows
- Accessibility testing with axe-core and keyboard navigation checks
Advanced Patterns
📄 Read: references/advanced-patterns.md
- Cascading date pickers (dependent availability)
- Dynamic date ranges driven by business logic
- Blackout/unavailable dates and recurring date handling
- Testing and validation patterns for advanced scenarios
Quick Start Example
Basic DatePicker implementation in Angular 21+ standalone component:
import { Component } from '@angular/core';
import { DatePickerModule } from '@syncfusion/ej2-angular-calendars';
@Component({
selector: 'app-datepicker-demo',
standalone: true,
imports: [DatePickerModule],
template: `
<ejs-datepicker
placeholder="Select date"
[(ngModel)]="selectedDate"
(change)="onDateChange($event)">
</ejs-datepicker>
<p>Selected: {{ selectedDate | date:'fullDate' }}</p>
`
})
export class DatePickerDemoComponent {
selectedDate: Date | null = null;
onDateChange(event: any) {
console.log('Date changed:', event.value);
}
}
Setup Steps:
- Install
@syncfusion/ej2-angular-calendarspackage - Import
DatePickerModulein component - Add
<ejs-datepicker>element with properties - Bind to component variable with
[(ngModel)](two-way binding)
What happens:
- DatePicker displays with calendar icon
- Click to open popup calendar
- Select date from calendar or type directly
- Selected date updates component variable
- change event fires on date selection
Common Patterns
1. Date Range Validation
Restrict user to select dates between specific start and end dates:
minDate = new Date(2024, 0, 1); // Jan 1, 2024
maxDate = new Date(2024, 11, 31); // Dec 31, 2024
<ejs-datepicker
[min]="minDate"
[max]="maxDate"
placeholder="Select date in 2024">
</ejs-datepicker>
Use case: Flight booking, hotel reservations, appointment scheduling
2. Custom Date Format
Display dates in application-specific format:
dateFormat = 'dd/MM/yyyy'; // European format
<ejs-datepicker
[format]="dateFormat"
placeholder="DD/MM/YYYY">
</ejs-datepicker>
3. Masked Date Input
Guide user with visual masks and arrow key navigation:
<ejs-datepicker
[enableMask]="true"
[maskPlaceholder]="'day'"
format="dd/MM/yyyy">
</ejs-datepicker>
Keyboard navigation: Up/Down arrows increment/decrement segments, Left/Right navigate between segments
4. Date Range Selection (With Min/Max)
Prevent past dates in booking scenarios:
minDate = new Date(); // Today
maxDate: Date;
constructor() {
// Set max to 90 days from today
this.maxDate = new Date();
this.maxDate.setDate(this.maxDate.getDate() + 90);
}
5. Reactive Forms Integration
DatePicker with reactive form validation:
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
export class FormComponent {
form = this.fb.group({
birthDate: [null, [Validators.required]],
});
constructor(private fb: FormBuilder) {}
}
<form [formGroup]="form">
<ejs-datepicker
formControlName="birthDate"
placeholder="Birth date">
</ejs-datepicker>
<span *ngIf="form.get('birthDate')?.hasError('required')">
Birth date is required
</span>
</form>
API Reference (Properties, Methods, Events)
Properties
| Property | Type | Notes |
|---|---|---|
allowEdit |
boolean | Whether textbox is editable (defaults true) |
calendarMode |
CalendarType | Calendar type (e.g., Gregorian, Islamic) |
cssClass |
string | Root CSS class for custom styling |
dayHeaderFormat |
DayHeaderFormats | Day header format (Short/Narrow/Abbreviated/Wide) |
depth |
CalendarView | Deepest allowed calendar view (Month/Year/Decade) |
enableMask |
boolean | Enable masked date input |
enablePersistence |
boolean | Persist component state between reloads |
enableRtl |
boolean | Enable right-to-left rendering |
enabled |
boolean | Enable or disable the component (set false to disable) |
firstDayOfWeek |
number | First day of week (0-6) |
floatLabelType |
FloatLabelType | string |
format |
string|FormatObject | Display format for the value |
fullScreenMode |
boolean | Popup full-screen mode on mobile |
htmlAttributes |
{ [key:string]: string } | Additional HTML attributes for root element |
inputFormats |
string[]|FormatObject[] | Acceptable input formats for parsing |
keyConfigs |
{ [key:string]: string } | Custom key action mappings |
locale |
string | Override global culture (e.g., 'en-US') |
maskPlaceholder |
MaskPlaceholderModel | Placeholder text for masked input |
max |
Date | Maximum selectable date |
min |
Date | Minimum selectable date |
openOnFocus |
boolean | Open popup on input focus |
placeholder |
string | Input placeholder text |
readonly |
boolean | Make input readonly (no typing) |
serverTimezoneOffset |
number | Server timezone offset in minutes (optional) |
showClearButton |
boolean | Show/hide clear icon |
showTodayButton |
boolean | Show/hide today button in popup |
start |
CalendarView | Initial view when popup opens |
strictMode |
boolean | Enforce strict parsing/validation |
value |
Date | Selected date value |
weekNumber |
boolean | Show week numbers in calendar |
weekRule |
WeekRule | Rule for first week of year |
width |
number|string | Component width |
zIndex |
number | Z-index for popup |
Methods
currentView()— Returns current calendar view namedestroy()— Destroy the component instancefocusIn()— Focus the inputfocusOut()— Blur the inputgetPersistData()— Returns persisted properties stringhide()— Hide the calendar popupnavigateTo(view: CalendarView, date?: Date)— Navigate to specific view/dateremoveDate(dates: Date|Date[])— Remove date(s) from valuesshow()— Show the calendar popup
Events
blur— Emits when input loses focuschange— Emits when the value changes (providesChangedEventArgs)cleared— Emits when clear button is usedclose— Emits when popup closes (preventable)created— Component created lifecycledestroyed— Component destroyed lifecyclefocus— Emits when input gets focusnavigated— Emits when calendar navigates to another viewopen— Emits when popup opens (preventable)renderDayCell— Emits for each day cell render (useful to disable/customize cells)
Common Use Cases
- Birthday/Birth Date Selection: Min/Max validation, masked input, decade start view for quick year selection
- Meeting Scheduler: Date range (today + 90 days), custom working day validation, form integration
- Hotel/Flight Booking: Min/Max dates, two-way date binding, reactive forms with validation
- Application Forms: Date of birth, license expiry, appointment dates with accessibility compliance
- International Applications: Locale-aware formatting, RTL support, culture-specific calendars
DateRangePicker
A comprehensive guide for implementing the Syncfusion Essential JS 2 DateRangePicker component in Angular applications. Learn to create date range pickers, handle range selection, manage events, and customize styling.
DateRangePicker Overview
The Syncfusion Angular DateRangePicker component is a specialized date selection widget that provides:
- Dual calendar display: Start and end date selection with synchronized calendars
- Preset ranges: Predefined options like "Last 7 Days", "This Month", "Last Month", "Custom"
- Range validation: Min/max dates, disabled ranges, required range length
- Date formatting: Customizable date format with separators and pattern support
- Event system: Created, destroyed, change, select, rangeSelected, open, close, renderDayCell events
- Keyboard shortcuts: Tab, arrow keys, enter, escape for full keyboard accessibility
- Localization support: Locale-specific formatting, day headers, month names
- Accessibility: Full WCAG 2.2 compliance, ARIA attributes, screen reader support
- Rich customization: CSS classes, custom templates, day cell rendering
- Mobile optimization: Touch-friendly interface, responsive design, full-screen mode
Package: @syncfusion/ej2-angular-calendars
Documentation Navigation
Read the following references based on your specific needs:
Getting Started
📄 Read: references/getting-started.md
- Package installation and module setup
- CSS theme imports and dependencies
- Basic DateRangePicker implementation
- Component initialization in Angular
- Start and end date configuration
- Running and testing setup
Date Range Selection
📄 Read: references/date-range-selection.md
- Single click range selection
- Sequential date selection (click start, then end)
- Date range value binding (
startDate,endDateproperties) - Min/max date constraints
- Range validation and error handling
- Disabled date ranges
- Clearing selections
Preset Ranges
📄 Read: references/preset-ranges.md
- Predefined range options (Last 7 Days, Last Month, etc.)
- Custom preset configuration
- Programmatic preset application
- Dynamic preset generation
- Preset change events
- Combining presets with constraints
Events & Methods
📄 Read: references/events-and-methods.md
- Event handlers (change, select, rangeSelected, open, close)
- Range selection event details (startDate, endDate, daySpan)
- Programmatic methods (show(), hide(), getSelectedRange())
- Created and destroyed lifecycle events
- RenderDayCell for custom styling
- Method return types and parameters
Date Formatting & Constraints
📄 Read: references/date-formatting-and-constraints.md
- Date format patterns and separators
- Multiple format support (format and inputFormats)
- Min/max date constraints
- Min/max days validation
- Disabled dates configuration
- Format error handling
- Locale-specific formats
Keyboard Navigation & Accessibility
📄 Read: references/keyboard-navigation-and-accessibility.md
- Tab and Shift+Tab navigation
- Arrow keys for date navigation
- Enter for range selection and confirmation
- Escape to close picker
- Alt key shortcuts
- Screen reader compatibility
- ARIA labels and roles
- WCAG 2.2 AA compliance
- Focus management
Styling & Customization
📄 Read: references/styling-and-customization.md
- CSS class customization (.e-daterangepicker, .e-calendar, .e-range-header)
- Theme selection (Material, Bootstrap, Tailwind, Fabric)
- Dark mode implementation
- Custom day cell styling via renderDayCell
- Disabled date styling
- Preset button styling
- Hover and focus states
- Responsive layout customization
Globalization & Localization
📄 Read: references/globalization-and-localization.md
- Locale property for date formatting
- RTL (Right-to-Left) support for Arabic, Hebrew
- Day header formats (Short, Narrow, Abbreviated, Wide)
- Month names and day names localization
- Custom locale support
- Timezone handling
- Date format localization
API Reference
📄 Read: references/api-reference.md
- Complete property reference with descriptions
- All method signatures with return types
- Event argument types and structures
- Type interfaces (RangeEventArgs, NavigatingEventArgs, etc.)
- CSS classes and styling hooks
- Browser support matrix
Quick Start Example
// app.component.ts
import { Component } from '@angular/core';
import { RangeEventArgs } from '@syncfusion/ej2-calendars';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Date range properties
startDate: Date = new Date(2026, 2, 1); // March 1, 2026
endDate: Date = new Date(2026, 2, 31); // March 31, 2026
// Constraints
minDate: Date = new Date(2020, 0, 1);
maxDate: Date = new Date(2030, 11, 31);
// Range display
selectedRange: string = '';
// Event handler
onRangeChange(args: RangeEventArgs): void {
console.log('Start Date:', args.startDate);
console.log('End Date:', args.endDate);
console.log('Days in range:', args.daySpan);
this.updateRangeDisplay();
}
updateRangeDisplay(): void {
if (this.startDate && this.endDate) {
const start = this.startDate.toLocaleDateString();
const end = this.endDate.toLocaleDateString();
this.selectedRange = `${start} - ${end}`;
}
}
}
<!-- app.component.html -->
<div style="padding: 20px; font-family: Arial, sans-serif;">
<h2>DateRangePicker Example</h2>
<div style="margin-bottom: 20px;">
<label for="dateRange">Select Date Range:</label>
<ejs-daterangepicker
id="dateRange"
placeholder="Select a date range"
[startDate]="startDate"
[endDate]="endDate"
[min]="minDate"
[max]="maxDate"
(change)="onRangeChange($event)">
</ejs-daterangepicker>
</div>
<div *ngIf="selectedRange" style="padding: 10px; background-color: #f0f0f0;">
<p><strong>Selected Range:</strong> {{ selectedRange }}</p>
</div>
</div>
/* app.component.css */
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-calendars/styles/material3.css';
:host ::ng-deep .e-daterangepicker {
margin: 10px 0;
width: 100%;
}
:host ::ng-deep .e-range-header {
background-color: #3f51b5;
color: white;
}
Common Patterns
Pattern 1: Preset Date Ranges
Quick selection buttons for common date ranges:
export class AppComponent {
presets: any[] = [
{ label: 'Today', start: new Date(), end: new Date() },
{ label: 'Last 7 Days', start: this.getDateDaysAgo(7), end: new Date() },
{ label: 'Last 30 Days', start: this.getDateDaysAgo(30), end: new Date() },
{ label: 'This Month', start: this.getFirstDayOfMonth(), end: new Date() },
{ label: 'Last Month', start: this.getFirstDayOfLastMonth(), end: this.getLastDayOfLastMonth() }
];
startDate: Date = new Date();
endDate: Date = new Date();
selectPreset(preset: any): void {
this.startDate = preset.start;
this.endDate = preset.end;
}
private getDateDaysAgo(days: number): Date {
const date = new Date();
date.setDate(date.getDate() - days);
return date;
}
private getFirstDayOfMonth(): Date {
return new Date(new Date().getFullYear(), new Date().getMonth(), 1);
}
private getFirstDayOfLastMonth(): Date {
const date = new Date();
return new Date(date.getFullYear(), date.getMonth() - 1, 1);
}
private getLastDayOfLastMonth(): Date {
const date = new Date();
return new Date(date.getFullYear(), date.getMonth(), 0);
}
}
<div>
<div style="margin-bottom: 10px;">
<button *ngFor="let preset of presets"
(click)="selectPreset(preset)"
style="margin-right: 5px; padding: 8px 12px;">
{{ preset.label }}
</button>
</div>
<ejs-daterangepicker
[startDate]="startDate"
[endDate]="endDate">
</ejs-daterangepicker>
</div>
Pattern 2: Date Range Validation
Validate date ranges with custom constraints:
export class AppComponent {
@ViewChild('daterangepicker') drp!: DateRangePickerComponent;
startDate: Date = new Date();
endDate: Date = new Date();
rangeError: string = '';
minDate: Date = new Date(2020, 0, 1);
maxDate: Date = new Date(2030, 11, 31);
minDays: number = 1; // At least 1 day
maxDays: number = 90; // At most 90 days
onRangeChange(args: RangeEventArgs): void {
this.rangeError = '';
// Validate date range
if (args.daySpan < this.minDays) {
this.rangeError = `Range must be at least ${this.minDays} day(s)`;
return;
}
if (args.daySpan > this.maxDays) {
this.rangeError = `Range cannot exceed ${this.maxDays} days`;
return;
}
this.startDate = args.startDate;
this.endDate = args.endDate;
}
isRangeValid(): boolean {
return this.rangeError === '';
}
}
Pattern 3: Reactive Form Integration
Integrate DateRangePicker with Reactive Forms:
export class AppComponent implements OnInit {
reportForm: FormGroup;
constructor(private fb: FormBuilder) {
this.reportForm = this.fb.group({
reportName: ['', Validators.required],
startDate: [new Date(2026, 0, 1), Validators.required],
endDate: [new Date(), Validators.required]
});
}
ngOnInit(): void {
this.reportForm.get('startDate')?.valueChanges.subscribe(date => {
console.log('Start date changed:', date);
this.validateDateRange();
});
this.reportForm.get('endDate')?.valueChanges.subscribe(date => {
console.log('End date changed:', date);
this.validateDateRange();
});
}
validateDateRange(): void {
const start = this.reportForm.get('startDate')?.value;
const end = this.reportForm.get('endDate')?.value;
if (start && end && start > end) {
this.reportForm.get('endDate')?.setErrors({ 'invalidRange': true });
} else {
this.reportForm.get('endDate')?.setErrors(null);
}
}
submitForm(): void {
if (this.reportForm.valid) {
console.log('Form values:', this.reportForm.value);
}
}
}
<form [formGroup]="reportForm" (ngSubmit)="submitForm()">
<div>
<label>Report Name:</label>
<ejs-textbox
formControlName="reportName"
placeholder="Enter report name">
</ejs-textbox>
</div>
<div>
<label>Report Period:</label>
<ejs-daterangepicker
[formControl]="reportForm.get('startDate')"
[endDate]="reportForm.get('endDate')?.value">
</ejs-daterangepicker>
</div>
<button type="submit" [disabled]="!reportForm.valid">Generate Report</button>
</form>
Pattern 4: Dynamic Range Constraints
Update range constraints based on business logic:
export class AppComponent {
startDate: Date = new Date();
endDate: Date = new Date();
// Dynamic constraints
minDate: Date = new Date();
maxDate: Date = new Date();
reportType: string = 'daily';
onReportTypeChange(type: string): void {
this.reportType = type;
this.updateConstraints();
}
private updateConstraints(): void {
const today = new Date();
switch (this.reportType) {
case 'daily':
// Last 7 days only
this.minDate = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
this.maxDate = today;
break;
case 'monthly':
// Last 12 months
this.minDate = new Date(today.getFullYear() - 1, today.getMonth(), 1);
this.maxDate = today;
break;
case 'yearly':
// Last 5 years
this.minDate = new Date(today.getFullYear() - 5, 0, 1);
this.maxDate = today;
break;
}
}
}
Pattern 5: Disabled Date Ranges
Disable specific date ranges (holidays, blackout dates):
export class AppComponent {
disabledRanges: Array<{start: Date, end: Date}> = [
{ start: new Date(2026, 11, 20), end: new Date(2026, 11, 31) }, // Christmas season
{ start: new Date(2026, 0, 1), end: new Date(2026, 0, 3) } // New Year
];
startDate: Date = new Date();
endDate: Date = new Date();
onRenderDayCell(args: RenderDayCellEventArgs): void {
// Disable dates in disabled ranges
for (const range of this.disabledRanges) {
if (args.date >= range.start && args.date <= range.end) {
args.isDisabled = true;
break;
}
}
}
}
Key Props Reference
| Prop | Type | Description | Example |
|---|---|---|---|
startDate |
Date |
Start date of the range | [startDate]="start" |
endDate |
Date |
End date of the range | [endDate]="end" |
value |
Date[] or DateRange |
Selected date range (array or object) | [(ngModel)]="dateRange" |
min |
Date |
Minimum selectable date | [min]="minDate" |
max |
Date |
Maximum selectable date | [max]="maxDate" |
minDays |
number |
Minimum days in range | [minDays]="1" |
maxDays |
number |
Maximum days in range | [maxDays]="90" |
format |
string |
Date display format | format="dd/MM/yyyy" |
separator |
string |
Range separator character | separator=" to " |
placeholder |
string |
Placeholder text | placeholder="Select date range" |
presets |
PresetsModel[] |
Predefined range options | [presets]="presets" |
strictMode |
boolean |
Strict date validation | [strictMode]="true" |
readonly |
boolean |
Read-only input field | [readonly]="false" |
enabled |
boolean |
Enable/disable component | [enabled]="true" |
locale |
string |
Culture/language code | locale="en-US" |
enableRtl |
boolean |
Enable RTL layout | [enableRtl]="false" |
cssClass |
string |
Custom CSS classes | cssClass="custom-drp" |
width |
number | string |
Component width | width="300px" |
allowEdit |
boolean |
Allow manual text input | [allowEdit]="true" |
openOnFocus |
boolean |
…(truncated)