Working with a calendar inside a native app is not the easiest task as it’s most of the time strongly connected to the OS. However, there are many operations we can perform on the calendar even from our Ionic app so let’s so how far we can go!
In this Quick Win we will use the Ionic Native calendar plugin to access the users calendar as well as some of the events. However, there are differences between iOS and Android how we can access them, but the creation of new events should work on both platforms!
Prepare Your Ionic App
We start with a blank new app and install the Ionic Native plugin and add the Cordova plugin as well:
1 2 3 4 |
ionic start calendarIntegration blank cd calendarIntegration ionic cordova plugin add cordova-plugin-calendar npm install --save @ionic-native/calendar |
Note that you need to test this functionality on a device as the plugin won’t work inside your brwoser!
Also make sure to add the plugin inside your app/app.module.ts like this
1 2 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 32 |
import { BrowserModule } from '@angular/platform-browser'; import { ErrorHandler, NgModule } from '@angular/core'; import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; import { SplashScreen } from '@ionic-native/splash-screen'; import { StatusBar } from '@ionic-native/status-bar'; import { MyApp } from './app.component'; import { HomePage } from '../pages/home/home'; import { Calendar } from '@ionic-native/calendar'; @NgModule({ declarations: [ MyApp, HomePage ], imports: [ BrowserModule, IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp, HomePage ], providers: [ StatusBar, SplashScreen, {provide: ErrorHandler, useClass: IonicErrorHandler}, Calendar ] }) export class AppModule {} |
Now you are ready to access the calendars, as the plugin will automatically ask for the permissions. If the user denies access there are also functions to ask for read/write permissions again, simply check out the docs for more information then.
Loading Calendar Data
Our first view consists of a list of all calendars of the users. We can load a list through the plugin and display them in a simple list with some information.
Additionally we add the functions to go into one calendar which we handle on another page and also the addEvent()
function which brings up a dialog for a new event.
You can also handle this silently to add events, in our case we picked the createEventInteractivelyWithOptions()
function which allows to set many details of the new event directly by passing the options to the call of the plugin!
Go ahead and change your pages/home.ts to:
1 2 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 32 33 |
import { Component } from '@angular/core'; import { NavController, Platform } from 'ionic-angular'; import { Calendar } from '@ionic-native/calendar'; @Component({ selector: 'page-home', templateUrl: 'home.html' }) export class HomePage { calendars = []; constructor(public navCtrl: NavController, private calendar: Calendar, private plt: Platform) { this.plt.ready().then(() => { this.calendar.listCalendars().then(data => { this.calendars = data; }); }) } addEvent(cal) { let date = new Date(); let options = { calendarId: cal.id, calendarName: cal.name, url: 'https://ionicacademy.com', firstReminderMinutes: 15 }; this.calendar.createEventInteractivelyWithOptions('My new Event', 'Münster', 'Special Notes', date, date, options).then(res => { }, err => { console.log('err: ', err); }); } openCal(cal) { this.navCtrl.push('CalDetailsPage', { name: cal.name }) } } |
Now we got the list of data and only need to display them in a simple ngFor. To access our 2 functions we also add buttons to each of the items which call the according functions. Change your pages/home.html to display a list of calendars like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<ion-header> <ion-navbar color="primary"> <ion-title> My Calendars </ion-title> </ion-navbar> </ion-header> <ion-content> <ion-list> <ion-item *ngFor="let cal of calendars" tappable> <button ion-button icon-only item-start clear (click)="addEvent(cal)"> <ion-icon name="add"></ion-icon> </button> {{ cal.name }} <p>{{ cal.type }}</p> <button ion-button icon-only item-end clear (click)="openCal(cal)"> <ion-icon name="arrow-forward"></ion-icon> </button> </ion-item> </ion-list> </ion-content> |
You can now already run this and add events, but let’s also add another function.
Listing Calendar Events
This is where iOS and Android are different: On iOS we can receive all events for a calendar. We simply use the name of the calendar, however this might cause problems if the user has multiple calendars with the same name. There’s already an open issue on the official plugin but at the moment this might cause a problem!
On Android we can only ask for events in a certain range, therefore we just use a start and end date so we get all events of the upcoming 31 days.
All those events will be stored in a local array which we use in the view in the next step. For now change your pages/cal-details.ts to:
1 2 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 32 |
import { Component } from '@angular/core'; import { IonicPage, NavController, NavParams, Platform } from 'ionic-angular'; import { Calendar } from '@ionic-native/calendar'; @IonicPage() @Component({ selector: 'page-cal-details', templateUrl: 'cal-details.html', }) export class CalDetailsPage { calName = ''; events = []; constructor(public navCtrl: NavController, public navParams: NavParams, private calendar: Calendar, private plt: Platform) { this.calName = navParams.get('name'); if (this.plt.is('ios')) { this.calendar.findAllEventsInNamedCalendar(this.calName).then(data => { this.events = data; }); } else if (this.plt.is('android')) { let start = new Date(); let end = new Date(); end.setDate(end.getDate() + 31); this.calendar.listEventsInRange(start, end).then(data => { this.events = data; }); } } } |
As said, we finish this tutorial with the last view which I guess doesn’t need any comment as it’s a simple list of cards. The only problem here was that the Angular DatePipe was not working with the dates of the events, so if you want to convert them accordingly perhaps create your own pipe and use something like MomentJS.
Open your pages/cal-details.html and change it to:
1 2 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 |
<ion-header> <ion-navbar color="primary"> <ion-title>{{ calName }}</ion-title> </ion-navbar> </ion-header> <ion-content> <ion-card *ngFor="let ev of events"> <ion-card-header> {{ ev.title }} </ion-card-header> <ion-card-content> <ion-list no-lines> <ion-item> <ion-icon name="calendar"></ion-icon> Start: {{ ev.startDate }} </ion-item> <ion-item> <ion-icon name="calendar"></ion-icon> End: {{ ev.endDate }} </ion-item> <ion-item> <ion-icon name="locate"></ion-icon> {{ ev.location }} </ion-item> </ion-list> </ion-card-content> </ion-card> </ion-content> |
NOTE: The returned values from your Google Calendar now have different names. You can log it out and you’ll see that they are now dtstart, dtend and eventLocation.
Therefore, you would have to change the according part of the view or rename them before adding them locally to your array.
Now your app is ready to list calendars, create new events and also display a list of events!
There is a lot more you can do like removing or changing events or adding events without the user noticing it. Use your power wisely and don’t spam the users calendar!
You can find a video version of this Quick Win below.
why cant run in browser?
+1
I was the same and then I debugged it by printing the json data returned (in cal-details.ts) to the console. The properties in the JSON that i have seen returned are not the same as the properties that are being output to the cal-details.html view in this tutorial (Things may have changed since he wrote this). So these are the changes you should make to cal-details.html: 1. where it says {{ev. startDate}} you should put {{ev.dtstart}} 2. where it says {{ev.endDate}} you should put {{ev.dtend}} 3. where it says {{ ev.location }} you should put {{ ev.eventLocation }} also the date pipe DOES work now so to display the dates properly put {{ev.dtstart | date}} etc
Hi
Can you please tell me how to block swipe 2 months before this month and 10 months after this month.
Assume like now we are in April month , from calendar we can swipe to previous side up to January this year and swipe to forward side up to march next year.
can you please tell me how block swiping after this months in ionic 2 calendar.
Thank you
i also cannot view in android. it doesnt show any output
Hi, very good job! A question, the event will be notified by an alarm? what is appen if the user will switch the mobile off and restart? thanks.