Angular Component
FullCalendar seamlessly integrates with the Angular 12 - 18. It provides a component that exactly matches the functionality of FullCalendar’s standard API.
This component is built and maintained by irustm in partnership with the maintainers of FullCalendar. It is the official Angular connector, released under an MIT license, the same license the standard version of FullCalendar uses. Useful links:
- Browse the Github repo (please star it!)
- Bug report instructions
- Example projects: Angular 18 | 17 | 16 | 15 | 14 | 13 | 12
This guide does not go into depth about initializing an Angular project. Please consult the aforementioned example/runnable projects for that.
The first step is to install the FullCalendar-related dependencies. You’ll need FullCalendar core, the Angular adapter, and any plugins you plan to use:
npm install --save \
@fullcalendar/core \
@fullcalendar/angular \
@fullcalendar/daygrid \
@fullcalendar/interaction
You must then include the FullCalendarModule
into your app’s root module. An example app (app.module.ts):
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FullCalendarModule } from '@fullcalendar/angular';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FullCalendarModule // register FullCalendar with your app
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Then, in one of your app’s component files (app.component.ts), prepare an object of options along with any plugins:
import { Component } from '@angular/core';
import { CalendarOptions } from '@fullcalendar/core'; // useful for typechecking
import dayGridPlugin from '@fullcalendar/daygrid';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
calendarOptions: CalendarOptions = {
initialView: 'dayGridMonth',
plugins: [dayGridPlugin]
};
}
Then, in your component’s template file (app.component.html), you have access to the <full-calendar>
tag. You must pass your options into this declaration!
<full-calendar [options]="calendarOptions"></full-calendar>
Inputs and Emitted Events
Angular has the concept of bound input data (written with [brackets]
) versus outputs (written with (parentheses)
). For the FullCalendar connector, there is no distinction between inputs and outputs. Everything is passed into the master options
input as key-value pairs. Here is an example that demonstrates passing in an events
array and a dateClick
handler:
import { Component } from '@angular/core';
import { CalendarOptions } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
calendarOptions: CalendarOptions = {
initialView: 'dayGridMonth',
plugins: [dayGridPlugin, interactionPlugin],
dateClick: (arg) => this.handleDateClick(arg),
events: [
{ title: 'event 1', date: '2019-04-01' },
{ title: 'event 2', date: '2019-04-02' }
]
};
handleDateClick(arg) {
alert('date click! ' + arg.dateStr)
}
}
Template:
<full-calendar [options]="calendarOptions"></full-calendar>
Inputs for events
/eventSources
/resources
(new in v6)
Certain options are exposed as top-level component inputs for convenience. This works well with the async
template helper, which accepts an Observable
or Promise
. The above example rewritten:
import { Component } from '@angular/core';
import { CalendarOptions, EventInput } from '@fullcalendar/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
calendarOptions: CalendarOptions = {
initialView: 'dayGridMonth',
dateClick: (arg) => this.handleDateClick(arg)
};
eventsPromise: Promise<EventInput[]>;
handleDateClick(arg) {
alert('date click! ' + arg.dateStr);
}
}
Template:
<full-calendar
[options]="calendarOptions"
[events]="eventsPromise | async"
></full-calendar>
This technique is commonly used when working with NgRx. View a sample project »
Modifying Properties
You can modify FullCalendar’s options dynamically by reassigning them within the options object. This example toggles the weekends
option on and off:
import { Component } from '@angular/core';
import { CalendarOptions } from '@fullcalendar/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
calendarOptions: CalendarOptions = {
initialView: 'dayGridMonth',
weekends: false // initial value
};
toggleWeekends() {
this.calendarOptions.weekends = !this.calendarOptions.weekends // toggle the boolean!
}
}
and the template:
<button (click)="toggleWeekends()">toggle weekends</button>
<full-calendar [options]="calendarOptions"></full-calendar>
If you want to modify options that are complex objects, like headerToolbar or events, you’ll need to make a copy of the object, make your change, and then reassign it. If you DO NOT want to do this, you can have the angular connector recursively search for changes within your objects, though this comes at a slight performance cost. Set the deepChangeDetection
prop to "true"
:
<full-calendar
[options]="calendarOptions"
deepChangeDetection="true"
></full-calendar>
Nested Templates (new in v6)
Use the ng-template
tag to customize content-injection areas such as eventContent. Example:
<full-calendar [options]="calendarOptions">
<ng-template #eventContent let-arg>
<b>{{ arg.event.title }}</b>
</ng-template>
</full-calendar>
Explanation:
- The template is named via the
#
syntax. It must be the name of a content-injection area. - The template accepts a single implicit local variable which is named via the
let-*
syntax. In the above example,let-arg
names the variable “arg”. - The properties of the argument are documented alongside each content-injection area. For example see eventContent’s argument.
Calendar API
Hopefully you won’t need to do it often, but sometimes it’s useful to access the underlying Calendar
object for raw data and methods.
This is especially useful for controlling the current date. The initialDate prop will set the initial date of the calendar, but to change it after that, you’ll need to rely on the date navigation methods.
To do something like this, you’ll need to get ahold of the ViewChild reference. In the template:
<full-calendar #calendar [options]="calendarOptions"></full-calendar>
Once you’ve explicitly marked your child component (#calendar
), you can get the underlying Calendar
object via the getApi
method:
import { Component, ViewChild } from '@angular/core';
import { CalendarOptions } from '@fullcalendar/core';
import { FullCalendarComponent } from '@fullcalendar/angular';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
// references the #calendar in the template
@ViewChild('calendar') calendarComponent: FullCalendarComponent;
calendarOptions: CalendarOptions = {
initialView: 'dayGridMonth'
};
someMethod() {
let calendarApi = this.calendarComponent.getApi();
calendarApi.next();
}
}
FullCalendar Premium
How do you use FullCalendar Premium’s plugins with Angular? They are no different than any other plugin. Just follow the same instructions as you did dayGridPlugin
in the above example. If you plan to use resources, you’ll need the @fullcalendar/resource
package:
npm install --save \
@fullcalendar/core \
@fullcalendar/angular \
@fullcalendar/resource \
@fullcalendar/resource-timeline
Then, initialize your calendar. Make sure to include your schedulerLicenseKey:
import { Component } from '@angular/core';
import { CalendarOptions } from '@fullcalendar/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
calendarOptions: CalendarOptions = {
schedulerLicenseKey: 'XXX'
};
}
and the template:
<full-calendar [options]="calendarOptions"></full-calendar>