Angular Calendar Component Overview

    Angular Calendar is a UI component used for displaying dates and days in an app. Supporting different features, it enables users to easily manage calendar functionalities, drag and create events in a calendar, navigate to a preferred date in it, and show events in an Angular calendar month view, week view, or day view in a single click.

    The Ignite UI for Angular Calendar component, developed as a native Angular component, provides an easy and intuitive ways to display date information, enable dates or apply Angular calendar disable dates mode. Users can choose from three different selection modes - single selection, multi selection or range selection.

    Angular Calendar Example

    We created the following Angular Calendar example using the Ignite UI for Angular Calendar package. It quickly shows how a basic calendar looks and feels like, how users can choose and highlight a single date, and how to move back and forth to a specific date.

    Getting Started with Ignite UI for Angular Calendar

    To get started with the Ignite UI for Angular Calendar component, first you need to install Ignite UI for Angular. In an existing Angular application, type the following command:

    ng add igniteui-angular
    

    For a complete introduction to the Ignite UI for Angular, read the getting started topic.

    The next step is to import the IgxCalendarModule in your app.module.ts file.

    Note

    The IgxCalendarComponent also depends on the BrowserAnimationsModule and the HammerModule for touch interactions, so they need to be added to the AppModule as well:

    // app.module.ts
    ...
    import { HammerModule } from '@angular/platform-browser';
    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    import { IgxCalendarModule } from 'igniteui-angular';
    // import { IgxCalendarModule } from '@infragistics/igniteui-angular'; for licensed package
    
    @NgModule({
        ...
        imports: [..., BrowserAnimationsModule, HammerModule, IgxCalendarModule],
        ...
    })
    export class AppModule {}
    

    Alternatively, as of 16.0.0 you can import the IgxCalendarComponent as a standalone dependency, or use the IGX_CALENDAR_DIRECTIVES token to import the component and all of its supporting components and directives.

    // home.component.ts
    
    import { HammerModule } from '@angular/platform-browser';
    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    import { IGX_CALENDAR_DIRECTIVES } from 'igniteui-angular';
    // import { IGX_CALENDAR_DIRECTIVES } from '@infragistics/igniteui-angular'; for licensed package
    
    @Component({
        selector: 'app-home',
        template: '<igx-calendar></igx-calendar>',
        styleUrls: ['home.component.scss'],
        standalone: true,
        imports: [BrowserAnimationsModule, HammerModule, IGX_CALENDAR_DIRECTIVES]
        /* or imports: [BrowserAnimationsModule, HammerModule, IgxCalendarComponent] */
    })
    export class HomeComponent {}
    

    Now that you have the Ignite UI for Angular Calendar module or directives imported, you can start using the igx-calendar component.

    Note

    The IgxCalendarComponent uses the Intl Web API for localization and formatting of dates. Consider using appropriate polyfills if your target platform does not support them.

    Using the Angular Calendar

    Angular Single Selection Calendar

    Instantiating the IgxCalendarComponent is as easy as placing its selector element in the template. This will display the current month in the single selection calendar mode.

    <!-- app.component.html -->
    <!-- Single selection mode -->
    <igx-calendar></igx-calendar>
    

    Angular Calendar Multiselect

    We can easily change the default mode using the selection property:

    <!-- app.component.html -->
    <!-- Multi selection mode -->
    <igx-calendar selection="multi" [showWeekNumbers]="true"></igx-calendar>
    

    Angular Calendar Range Picker

    Following the same approach, we can switch to range selection mode:

    <!-- app.component.html -->
    <!-- Range selection mode -->
    <igx-calendar selection="range"></igx-calendar>
    

    Note

    Notice that the calendar header is not rendered when the selection is either multi or range.

    Localization and Formatting

    Due to their very nature, localization and formatting are essential to any calendar. In the IgxCalendarComponent those are controlled and customized through the following properties - locale, formatOptions, formatViews, weekStart.

    Let's go ahead and try those along with other customizations from the IgxCalendarComponent API. First thing we need to set is the weekStart, which controls the starting day of the week. It defaults to 0, which corresponds to Sunday, so we will set a value of 1 for Monday. In the markup below we are also binding the formatOptions and formatViews properties to customize the display formatting. Finally, we are binding the locale property to a value, based on the user's location choice:

    <!-- app.component.html -->
    <igx-select #select [(ngModel)]="locale">
        <igx-select-item *ngFor="let locale of locales" [value]="locale">
            {{ locale }}
        </igx-select-item>
    </igx-select>
    
    <igx-calendar #calendar
        [weekStart]="1"
        [locale]="locale"
        [formatOptions]="formatOptions"
        [formatViews]="formatViews">
    </igx-calendar>
    

    All property values should be set in the AppCоmponent file:

    // app.component.ts
    @ViewChild('calendar', { read: IgxCalendarComponent }) public calendar: IgxCalendarComponent;
    
    public formatOptions: any;
    public formatViews: any;
    public locales = ['EN', 'DE', 'FR', 'AR', 'ZH'];
    public locale = 'EN';
    
    public ngOnInit() {
        this.formatOptions = { day: '2-digit', month: 'long', weekday: 'long', year: 'numeric' };
        this.formatViews = { day: true, month: true, year: true };
    }
    

    If everything went well, we should now have a calendar with customized dates display, that also changes the locale representation, based on the user location. Let's have a look at it:

    How to Disable Dates In Angular Calendar

    This section demonstrates the usage of disabledDates functionality. For this purpose, different single dates or ranges can be added to an array and then passed to the disabledDates descriptor.

    The DateRangeType is used to specify a range that is going to be disabled.

    Let's create a sample that is disabling the dates between the 3rd and the 8th of the current month:

    export class CalendarSample6Component {
        @ViewChild('calendar') public calendar: IgxCalendarComponent;
        public today = new Date(Date.now());
        public range = [
            new Date(this.today.getFullYear(), this.today.getMonth(), 3),
            new Date(this.today.getFullYear(), this.today.getMonth(), 8)
        ];
    
        public ngOnInit() {
            this.calendar.disabledDates = [{ type: DateRangeType.Between, dateRange: this.range }];
        }
    }
    

    These configurions should have the following result:

    Special dates

    The specialDates feature is using almost the same configuration principles as the disabledDates. The ability to select and focus specialDates is what differs them from the disabled ones.

    Let's add some specialDates to our igxCalendar. In order to do this, we have to create a DateRangeDescriptor item of type DateRangeType.Specific and pass an array of dates as a dateRange:

    export class CalendarSample7Component {
        @ViewChild('calendar', { static: true })
        public calendar: IgxCalendarComponent;
        @ViewChild('alert', { static: true })
        public dialog: IgxDialogComponent;
        public range = [];
    
        public selectPTOdays(dates: Date[]) {
            this.range = dates;
        }
    
        public submitPTOdays(eventArgs) {
            this.calendar.specialDates =
                [{ type: DateRangeType.Specific, dateRange: this.range }];
    
            this.range.forEach((item) => {
                this.calendar.selectDate(item);
            });
    
            ...
        }
    }
    
    <igx-calendar #calendar weekStart="1"
        selection="multi"
        (selected)="selectPTOdays($event)">
    </igx-calendar>
    <igx-dialog #alert title="Request Time Off"
        leftButtonLabel="OK"
        (leftButtonSelect)="alert.close()">
    </igx-dialog>
    <button igxButton="contained" (click)="submitPTOdays($event)">Submit Request</button>
    

    The following demo illustrates a calendar with a vacation request option:

    Week numbers

    You can now use showWeekNumbers input to show the week numbers for both Calendar and DatePicker components.

    
    <!-- app.component.html -->
    <igx-calendar selection="multi" [showWeekNumbers]="true"></igx-calendar>
    

    The following demo illustrates a calendar with enabled week numbers:

    Calendar Events

    Let's explore the events emitted by the calendar:

    • selected - emitted when selecting date(s) in the calendar.
    • viewDateChanged - emitted every time when the presented month/year is changed - for example after navigating to the next or previous month.
    • activeViewChanged - emitted after the active view is changed - for example after the user has clicked on the month or year section in the header.
    <!-- app.component.html -->
    <igx-calendar #calendar
        (selected)="onSelection($event)"
        (viewDateChanged)="viewDateChanged($event)"
        (activeViewChanged)="activeViewChanged($event)">
    </igx-calendar>
    

    The selected event is suitable to build input validation logic. Use the code from below to alert the user if selection exceeds 5 days, and then reset the selection:

    // app.component.ts
    ...
    public onSelection(dates: Date[]) {
        if (dates.length > 5) {
            this.calendar.selectedDates = [];
            // alert the user
        }
    }
    public viewDateChanged(event: IViewDateChangeEventArgs) {
        // use event.previousValue to get previous month/year that was presented.
        // use event.currentValue to get current month/year that is presented.
    }
    
    public activeViewChanged(event: CalendarView) {
        // use CalendarView[event] to get the current active view (DEFAULT, YEAR or DECADE)
    }
    

    Use the demo below to play around (change selection, navigate through months and years) and see the events logged real time:

    Angular Calendar Views

    There are separate views provided by the IgxCalendarModule that can be used independently:

    Keyboard navigation

    If you traverse the page using Tab key you should keep in mind that based on W3 accessability recommendations the igxCalendarComponent now introduces the following tab stops:

    • Previous month button
    • Month selection button
    • Year selection button
    • Next month button
    • Selected date, Current date, First focusable (not disabled) date in the days view

    In an Angular Calendar that contains more than one selected dates, only the first date will be introduced as a tab stop. For example, when an Angular Calendar multiselect is enabled and you have selected the dates: 13/10/2020, 17/10/2020 and 21/10/2020 only 13/10/2020 will be accessible during tab navigation; in an Angular Calendar Range Picker, only the first date of the selected range will be part of the page tab sequence.

    Note

    Behavioral change, from v10.2.0 - Tab key navigation in the days view is no longer available. In order to navigate between the dates in the date view you should use the arrow keys.

    When the igxCalendar component is focused, use:

    • PageUp key to move to the previous month,
    • PageDown key to move to the next month,
    • Shift + PageUp keys to move to the previous year,
    • Shift + PageDown keys to move to the next year,
    • Home key to focus the first day of the current month or first month in view
    • End key to focus the last day of the current month or last month in view

    When the prev or the next month buttons (in the subheader) are focused, use:

    • Space or Enter key to scroll into view the next or previous month.

    When the months button (in the subheader) is focused, use:

    • Space or Enter key to open the months view.

    When the year button (in the subheader) is focused, use:

    • Space or Enter key to open the decade view.

    When a day inside the current month is focused:

    • Use Arrow keys to navigate through the days. Note: The disabled dates will be skipped.
    • Focus will be persisted on the current month that is in the view, while navigation from/to the last day/first day of the month.
    • THe kb navigation would be continuous, which means that it will go through all months while navigating with the arrows.
    • Use Enter key to select the currently focused day.

    When a month inside the months view is focused, use:

    • Arrow keys to navigate through the months.
    • Home key to focus the first month inside the months view.
    • End key to focus the last month inside the months view.
    • Enter key to select the currently focused month and close the view.

    When an year inside the decade view is focused, use:

    • Arrow up and Arrow down keys to navigate through the years,
    • Enter key to select the currently focused year and close the view.
    Note

    Following version 8.2.0, keyboard navigation will not focus days that are outside of current month, but will rather change the month in view.

    Multi View Calendar

    Multiview calendar supports all three types of selection. Use the monthsViewNumber input to set the number of displayed months, which will be shown horizontally in a flex container. There is no limit on the max value set. While using a multi view calendar, you may want to hide the days that do not belong to the current month. You are able to do it with the hideOutsideDays property. Keyboard navigation moves to next/previous months when those are in view.

    Styling

    To get started with styling the calendar, we need to import the index file, where all the theme functions and component mixins live:

    @use "igniteui-angular/theming" as *;
    
    // IMPORTANT: Prior to Ignite UI for Angular version 13 use:
    // @import '~igniteui-angular/lib/core/styles/themes/index';
    

    Following the simplest approach, we create a new theme that extends the calendar-theme and accepts some of the default theme's parameters.

    $custom-calendar-theme: calendar-theme(
      $header-background: #345779,
      $content-background: #fdfdfd,
      $header-text-color: #ffffff,
      $date-current-text-color: #2dabe8,
      $picker-arrow-color: #2dabe8,
      $date-selected-text-color: #fdfdfd,
      $date-current-bg-color: #fdfdfd,
      $picker-arrow-hover-color:  #345779,
      $year-current-text-color: #2dabe8,
      $year-hover-text-color: #2dabe8,
      $month-current-text-color: #2dabe8,
      $month-hover-text-color: #2dabe8,
      $picker-text-color: #2dabe8,
      $picker-text-hover-color:  #345779
    );
    

    Using CSS variables

    The last step is to pass the custom calendar theme:

     @include css-vars($custom-calendar-theme);
    

    Using Theme Overrides

    In order to style components for older browsers, like Internet Explorer 11, we have to use a different approach, since it doesn't support CSS variables.

    If the component is using the Emulated ViewEncapsulation, it is necessary to penetrate this encapsulation using ::ng-deep. To prevent the custom theme to leak into other components, be sure to include the :host selector before ::ng-deep:

    :host {
     ::ng-deep {
       @include calendar($custom-calendar-theme);
     }
    }
    

    API References

    Additional Resources

    Our community is active and always welcoming to new ideas.