Integrating the Calendar into your Ionic App

This post is more than 2 years old.

For today's demo, I decided to try something I've been meaning to make time for - integrating with the calendar on the mobile device. Luckily there is a great plugin for this - Calendar-PhoneGap-Plugin. This plugin provides all types of hooks into the local calendar including the ability to search and add events. With that plugin in place, I whipped up a quick demo.

I began by building an application that simply returned events from a list and displayed them as is. Here is the view:

Simulator Screen Shot Sep 18, 2015, 11.32.58 AM

Let's look at the code behind this. First, the HTML. Since this application is so simple, I'm not using routes and templates.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">

    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
    <link href="css/ionic.app.css" rel="stylesheet">
    -->

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>

    <!-- cordova script (this will be a 404 during development) -->
    <script src="cordova.js"></script>

    <!-- your app's js -->
    <script src="js/app.js"></script>
    <script src="js/controllers.js"></script>
    <script src="js/services.js"></script>
  </head>
  <body ng-app="starter">

    <ion-pane ng-controller="MainCtrl">
      <ion-header-bar class="bar-stable">
        <h1 class="title">Ionic Calendar Demo</h1>
      </ion-header-bar>
      <ion-content>
				
				<div class="card" ng-repeat="event in events">
					<div class="item item-divider">
						{{event.title}}
					</div>					
					<div class="item item-text-wrap">
						{{ event.description }}
						<p/>
						<strong>When: {{ event.date | date:'short' }}</strong>
					</div>
				</div>
				
      </ion-content>
    </ion-pane>
  </body>
</html>

This should all be fairly boiler plate. I simply loop over the events and create a card UI for each. Now let's look into the controller code.

angular.module('starter.controllers', [])

.controller('MainCtrl', function($scope, Events) {
	
	Events.get().then(function(events) {
		console.log("events", events);	
		$scope.events = events;
	});
	
});

Yep, just call the service and render the events. Trivial. Now let's look at the service.

angular.module('starter.services', [])

.factory('Events', function($q) {

	var incrementDate = function (date, amount) {
			var tmpDate = new Date(date);
			tmpDate.setDate(tmpDate.getDate() + amount)
			return tmpDate;
	};

	//create fake events, but make it dynamic so they are in the next week
	var fakeEvents = [];
	fakeEvents.push(
		{
			"title":"Meetup on Ionic",
			"description":"We'll talk about beer, not Ionic.",
			"date":incrementDate(new Date(), 1)
		}	
	);
	fakeEvents.push(
		{
			"title":"Meetup on Beer",
			"description":"We'll talk about Ionic, not Beer.",
			"date":incrementDate(new Date(), 2)
		}	
	);
	fakeEvents.push(
		{
			"title":"Ray's Birthday Bash",
			"description":"Celebrate the awesomeness of Ray",
			"date":incrementDate(new Date(), 4)
		}	
	);
	fakeEvents.push(
		{
			"title":"Code Review",
			"description":"Let's tear apart Ray's code.",
			"date":incrementDate(new Date(), 5)
		}	
	);
	
	var getEvents = function() {
			var deferred = $q.defer();
			deferred.resolve(fakeEvents);
			return deferred.promise;
	}
	
  return {
		get:getEvents
  };

});

Ok, so this is a bit more complex. I've got a set of fake data that creates four events in the future. The service then returns those fake events. Ok, so let's kick it up a notch. Given that our Calendar plugin can check for events, I'm going to update my code to display if an event has been added to the calendar or not. Here is an example.

Simulator Screen Shot Sep 18, 2015, 11.41.36 AM

In this screen shot, you can see buttons to add the event to your calendar. Notice that the third event though is recognized as being in the calendar. To make this work, I updated the service call for events to handle checking the calendar. It was a bit complex since each call is asynch, but $q makes it easy to handle that.

var getEvents = function() {
		var deferred = $q.defer();

		/*
		Logic is:
		For each, see if it exists an event.
		*/
		var promises = [];
		fakeEvents.forEach(function(ev) {
			//add enddate as 1 hour plus
			ev.enddate = incrementHour(ev.date, 1);
			console.log('try to find '+JSON.stringify(ev));
			promises.push($cordovaCalendar.findEvent({
				title:ev.title,
				startDate:ev.date
			}));
		});
		
		$q.all(promises).then(function(results) {
			console.log("in the all done");	
			//should be the same len as events
			for(var i=0;i<results.length;i++) {
				fakeEvents[i].status = results[i].length === 1;
			}
			deferred.resolve(fakeEvents);
		});
		
		return deferred.promise;
}

I set a status value on events to represent whether or not the event exists. Back on the display side, I handle this like so:

<p ng-if="event.status">This event is added to your calendar already!</p>
<button ng-if="!event.status" ng-click="addEvent(event,$index)" class="button button-block button-balanced">Add to Calendar</button>

Fairly simple, right? Now let's look at the add code. I'll skip the controller code as all it does is call the service and update the scope.

var addEvent = function(event) {
	var deferred = $q.defer();

	$cordovaCalendar.createEvent({
		title: event.title,
		notes: event.description,
		startDate: event.date,
		endDate:event.enddate
	}).then(function (result) {
		console.log('success');console.dir(result);
		deferred.resolve(1);
	}, function (err) {
		console.log('error');console.dir(err);
		deferred.resolve(0);
	});	
	
	return deferred.promise;

}

And just to prove it works - here is the event I just added:

Simulator Screen Shot Sep 18, 2015, 11.46.06 AM

I've put the full source code for this demo up on GitHub: https://github.com/cfjedimaster/Cordova-Examples/tree/master/calendarionic. I want to give big thanks to Eddy Verbruggen for helping me use his plugin, and for fixing a bug I encountered!

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Steven Pyle posted on 9/21/2015 at 10:22 AM

Works great! Thanks for sharing. I ran into two gotchas that other folks new to Ionic might also get stuck on. In order to use the Calendar-PhoneGap-Plugin, I had to run "bower install ngCordova" in my project. ng-cordova.js wasn't part of the default Ionic Framework project by default. Also, adding events to a calendar doesn't seem to work when using "ionic serve" to run the app in a browser. I had to use the emulator to see it work. I guess that makes sense since there is no calendar available when not using a device...?

Comment 2 (In reply to #1) by Raymond Camden posted on 9/21/2015 at 1:06 PM

Sorry, these are both things I just kinda assumed were obvious, but were absolutely *not* obvious and I should have called out.

Comment 3 by Diogo Rodrigues posted on 11/16/2015 at 11:16 AM

pls, pls. help me to make this run. what i need? i get the procjet https://github.com/cfjedima... and run "ionic serve". I need anything else?

Comment 4 (In reply to #3) by Raymond Camden posted on 11/16/2015 at 11:56 AM

It depends on what you mean. If you mean you want to use this on a device, then you need to set up the various mobile SDKs. This isn't on topic for this blog post, but I'd suggest picking up my Apache Cordova book (linked to from the About Me page).

Comment 5 by Dara posted on 11/21/2015 at 12:45 AM

nice .. thanks!

Comment 6 (In reply to #1) by Ramo posted on 11/23/2015 at 8:06 AM

Hi Steven. I had the same problem. I tried to see the calendar in my browser (Chrome). Then I understood that the calendar can be seen only on the device. I got in browser no code errors. After I installed the calendar I still don't see the it on my device. Then I read that I have to write my calander-controller in such a function:

document.addEventListener("deviceready", function () {
//embed Code here
});

Even that didn't help. Have you solved your problem? If yes, how?

Comment 7 (In reply to #6) by Raymond Camden posted on 11/23/2015 at 3:00 PM

Ramo, as you see, I replied to Steven that this was device only - sorry if you missed that comment. Also, deviceready is standard for Cordova apps. You *always* need to wait for it when doing plugin stuff.

Have you tried remote debug to see what error you get?

Comment 8 (In reply to #7) by Ramo posted on 11/24/2015 at 9:40 AM

Now I tried remote debug and got no errors. But the calendar is still not displayed. I get the following console output (see the pic):

Comment 9 (In reply to #8) by Raymond Camden posted on 11/24/2015 at 2:08 PM

So what happens when you click to add the event?

Comment 10 (In reply to #9) by Ramo posted on 11/25/2015 at 8:21 AM

Thanks for your kind support. I don't get the content of the calendar. My view is empty. No representation of the calendar. I've uploaded your code separately on GitHub. Would you please tell me what could be the problem? GitHub: https://github.com/ramogund...

Comment 11 (In reply to #10) by Raymond Camden posted on 11/25/2015 at 3:14 PM

Do you see where I left the else {} block empty? You should add some debugging there.

Comment 12 (In reply to #11) by Ramo posted on 11/30/2015 at 7:50 AM

Raymond, I wrote some things like this in else block: console.log("do some thing! "+result); I get nothing. The whole time empty View (see the pic). Have you ever looked the code on git: https://github.com/ramogund... I have taken one on one your code. and I get no errors and nothing displayed.

Comment 13 (In reply to #12) by Raymond Camden posted on 11/30/2015 at 2:00 PM

Ramo, why are you testing in the browser? I said *multiple* times this is device only. Did you not see that?

Comment 14 by Marc-André Langlais posted on 12/1/2015 at 10:21 AM

Hi Raymond,
thanks for the article, really useful.
Having issue with eventFind. I can create the events just fine... however, I can't seem to get eventFind to work. It works when I debug really slowly through the loops, but not when not debugging.
Code in .service (as opposed to .factory):

self.findEvents = function() {

var deferred = $q.defer();
var promises = [];
self.selectedTeam.Dates.forEach(function(date) {
date.Events.forEach(function(event){
...
// assign event params here
...
promises.push($cordovaCalendar.findEvent({
title: tt,
location: loc,
notes: nt,
startDate: stUTC,
endDate: enUTC
}));
});
});

$q.all(promises).
then(function(results) {
for(var i=0; i<results.length; i++)="" {="" if(results[i].length="=" 1){="" self.selectedteam.stats="cat" ;="" }="" }="" deferred.resolve(self.selectedteam);="" });="" return="" deferred.promise;="" }="">

Comment 15 (In reply to #14) by Raymond Camden posted on 12/1/2015 at 11:53 AM

If it works when you debug, it seems to imply an async issue. Maybe share the code thats calling the service?

Comment 16 (In reply to #15) by Marc-André Langlais posted on 12/2/2015 at 2:23 AM

Calling it from a controller. The service is called huskyModel.
loadGameAPI uses a $http service that runs just fine right before that.

.controller('gameController', ['$http', '$cordovaCalendar','huskyModel', function($http, $cordovaCalendar, huskyModel) {
var self = this;
var foundDate = null;
self.huskyModel = huskyModel;

self.huskyModel.loadGameAPI();
foundDate = self.huskyModel.findEvents();

Comment 17 (In reply to #13) by Ramo posted on 12/2/2015 at 12:21 PM

Of course I always test on the device. The screenshot what you see above looks the same also on the device, so just empty, no calander view. I meant the screenshot as an example.

Comment 18 (In reply to #17) by Raymond Camden posted on 12/2/2015 at 2:24 PM

And when you tested on device, and used CHrome Remote debug, did you see anything in console?

Comment 19 (In reply to #16) by Raymond Camden posted on 12/2/2015 at 2:24 PM

It doesn't look like you are properly using the async result from your code. Your treating it as sync, not async.

Comment 20 (In reply to #19) by Marc-André Langlais posted on 12/2/2015 at 2:32 PM

Do you have a suggestion? How should I be using the result? Am I limited on how I use the result? foundDate is a bool that is binded to a UI component.

Comment 21 (In reply to #20) by Raymond Camden posted on 12/2/2015 at 2:36 PM

If you look at my code, I show you how to work with the promises returned from my service/factory.

Comment 22 (In reply to #21) by Marc-André Langlais posted on 12/2/2015 at 2:46 PM

self.huskyModel.findEvents();You simply binded the resolved property status for each fakeEvent, which is exactly what I did. The function self.huskyModel.findEvents(); updates properties in the service that are binded to the UI.
Regardless of the returned value, the resolved values should be reflected in the properties that were updated.
For example.. you can assign your resolved fakeEvents collection to anything, the fakeEvents[].status should be updated after the findEvent right?

Comment 23 (In reply to #22) by Raymond Camden posted on 12/2/2015 at 2:50 PM

I'm not quite sure I get what you are saying. In my code, findEvents returned an async result. You can't just do x = foo.findEvents(); because it isn't finished processing in the initial result.

If you switch your code back to my original code, and confirm it works, maybe you can then slowly re-add your mods back in so we can see where it breaks.

Comment 24 (In reply to #23) by Marc-André Langlais posted on 12/2/2015 at 2:56 PM

Good idea. I will attempt it later on in the night :)
Thanks Raymond!

Comment 25 (In reply to #18) by Ramo posted on 12/2/2015 at 3:19 PM

I get the following outputs in the following picture:

Comment 26 (In reply to #25) by Raymond Camden posted on 12/2/2015 at 3:24 PM

Hmm. No error. Not sure then why it is pure white on your screen. Sorry - but I'd have to take your code and run it here to help more, which would be a paid engagement for my time and services.

Comment 27 (In reply to #23) by Marc-André Langlais posted on 12/3/2015 at 9:14 AM

Hi Raymond... still same issue.
Code:
self.findEvents = function(){
var deferred = $q.defer();

/*
Logic is:
For each, see if it exists an event.
*/
var promises = [];
self.selectedTeam.Events.forEach(function(event) {
console.log('try to find '+event.id);
promises.push($cordovaCalendar.findEvent({
title: "Hockey - " + event.adversary +" - " + event.id,
location: event.arenaCity + event.arenaName,
notes: "Bonne partie! -" + event.id,
startDate: event.dateTime,
endDate: addMinutes(event.dateTime, 120)
}));
});

$q.all(promises).then(function(results) {
console.log("in the all done");
//should be the same len as events
for(var i=0;i<results.length;i++) {="" self.selectedteam.events[i].oncalendar="results[i].length" =="=" 1;="" }="" deferred.resolve(self.selectedteam.events);="" });="" return="" deferred.promise;="" }="">

Comment 28 (In reply to #27) by Marc-André Langlais posted on 12/3/2015 at 9:45 AM

...and what calls it:
self.huskyModel.findEvents().then(function(events){
console.log("events", events);
self.huskyModel.selectedTeam.Events = events;
});

Comment 29 (In reply to #28) by Raymond Camden posted on 12/3/2015 at 12:21 PM

If you use *exactly* my code, does it work?

Comment 30 (In reply to #25) by Felipe Zap de Mello posted on 12/3/2015 at 6:32 PM

Hi my friend , I had the same issue ,

in the controller, try to change the event deviceready from $ionicPlatform for this:

$window.document.addEventListener('deviceready', function(){});

more information here: https://github.com/EddyVerb...

Hope this helps!

Comment 31 by Felipe Zap de Mello posted on 12/3/2015 at 6:41 PM

For those who had the issue 'window.plugins is undefined'
In controller, try to change the event deviceready from $ionicPlatform for this:

$window.document.addEventListener('deviceready', function(){});

Don't forget to inject the variable $window

more information here: https://github.com/EddyVerb...
Hope this helps!

Comment 32 (In reply to #31) by Raymond Camden posted on 12/3/2015 at 8:47 PM

That shouldn't help though. Ionic's ready event wraps deviceready.

Comment 33 by salomon posted on 2/15/2016 at 1:58 PM

Hi Raymond, maybe you or somebody else here can help me with my question/problem. Creating calendars, adding events etc. works fine but how can I fetch the data from the calendar and show it in my app?

For example, this is the line for listing all calendars:

listCalendars(onSuccess, onError)

When I call this function, the App opens a pop-up-window which shows the calendars with their attributes.

I wanna display the calendars in a p-element instead of the pop-up and tried it with the following lines:

var x = listCalendars(onSuccess, onError).toString();

$( "#test" ).append(x);

It doesn't work and the app opens the same pop-up-window. Maybe you have some ideas?

Comment 34 (In reply to #33) by Raymond Camden posted on 2/15/2016 at 2:00 PM

The logic to handle (do X when done) should be in your onSuccess method. You may not understand how async operations work. Basically, listCalendars will run onSuccess when done, or onError, so your code to handle the result must be in onSuccess.

Comment 35 (In reply to #34) by salomon posted on 2/15/2016 at 3:13 PM

Thank you! This helps me a lot.

Comment 36 by Mohamed posted on 4/5/2016 at 2:59 PM

hello can i sent the event to the server via http at the same time of adding to my calender ???

Comment 37 by Messaoud Mohamed posted on 4/5/2016 at 3:01 PM

hello can i sent the event to the server via http at the same time of adding to my calender ???

Comment 38 (In reply to #37) by Raymond Camden posted on 4/5/2016 at 3:03 PM

Yes.

Comment 39 (In reply to #38) by Messaoud Mohamed posted on 4/5/2016 at 3:14 PM

and how ???

Comment 40 (In reply to #39) by Raymond Camden posted on 4/5/2016 at 3:15 PM

You would do it just like you do any other HTTP call in JavaScript, via an Ajax call using XHR. Do you know how to do that?

Comment 41 (In reply to #40) by Messaoud Mohamed posted on 4/5/2016 at 3:43 PM

actually no

Comment 42 (In reply to #41) by Raymond Camden posted on 4/5/2016 at 3:46 PM

Working with Ajax is a very important part of client-side JavaScript development. I'm pretty surprised you are working with hybrid mobile apps before you've learned that. I'd start off by doing some basic research - ie - Googling for it. As XHR is pretty old, you will find plenty of help. Actually, start here: https://developer.mozilla.o....

Comment 43 (In reply to #42) by Messaoud Mohamed posted on 4/5/2016 at 3:53 PM

Thankyou very much but i'm just try to learn by building some application
when i buil my application i get this erreur can u help please ??

* What went wrong:

A problem occurred configuring root project 'android'.

> Could not resolve all dependencies for configuration ':_armv7DebugCompile'.

> Could not find any version that matches com.android.support:support-v4:+.

Searched in the following locations:

https://repo1.maven.org/mav...

https://repo1.maven.org/mav...

https://download.01.org/cro...

https://download.01.org/cro...

file:/C:/Program Files (x86)/Android/android-sdk/extras/google/m2repository/com/android/support/support-v4/mav

file:/C:/Program Files (x86)/Android/android-sdk/extras/google/m2repository/com/android/support/support-v4/

Required by:

:android:unspecified

* Try:

Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

Comment 44 (In reply to #43) by Raymond Camden posted on 4/5/2016 at 3:54 PM

Ensure your Cordova/Ionic CLIs are fully up to date. Then - try a virgin Cordova project w/o any of my code, and ensure you can add the Android project and build for it.

Comment 45 by TC Mc Donalds posted on 4/6/2016 at 11:10 AM

@Raymond Camden
After installing the cordova-calendar-plugin, I not able to build the project.Please have a look at stacktrace.

error: cannot find symbol
if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this.cordova.getActivity(), type)) {
^
symbol: method checkSelfPermission(Activity,String)
location: class ContextCompat
/home/tushar/Documents/Sites/DailyGig_App/DailyGig_app/platforms/android/src/nl/xservices/plugins/Calendar.java:157: error: cannot find symbol
ActivityCompat.requestPermissions(
^
symbol: method requestPermissions(Activity,String[],int)
location: class ActivityCompat

Comment 46 (In reply to #44) by Messaoud Mohamed posted on 4/6/2016 at 11:41 AM

i do everythink i can build but when i run it it dosn't work in the device pleace how can i fix it and in the browser i have this proble :

ionic.bundle.js:19890 TypeError: Cannot read property 'calendar' of undefined

at Object.findEvent

Comment 47 (In reply to #45) by Raymond Camden posted on 4/6/2016 at 12:57 PM

You will need to file a bug report with the plugin unfortunately.

Comment 48 (In reply to #46) by Raymond Camden posted on 4/6/2016 at 12:58 PM

Sounds like you may have forgotten to install the plugin.

Comment 49 (In reply to #48) by Messaoud Mohamed posted on 4/6/2016 at 1:10 PM

cordova plugin add cordova-plugin-calendar i install it

Comment 50 (In reply to #49) by Raymond Camden posted on 4/6/2016 at 1:16 PM

When you use Chrome remote debug, do you see an error in the console there?

Comment 51 (In reply to #50) by Messaoud Mohamed posted on 4/6/2016 at 1:31 PM

it work with this plugin

$ cordova plugin add https://github.com/EddyVerb...

Comment 52 (In reply to #51) by Raymond Camden posted on 4/6/2016 at 1:35 PM

Ok, then I'd consider pinging him and telling him the issue you had.

Comment 53 (In reply to #52) by Messaoud Mohamed posted on 4/6/2016 at 1:43 PM

thank u very much but i still have a little problem that when i pass one event it work but i put it all it come blank

Comment 54 (In reply to #53) by Raymond Camden posted on 4/6/2016 at 1:45 PM

I'm having difficulty understanding your English. "but i put it all it come blank" - can you rephrase that?

Comment 55 (In reply to #54) by Messaoud Mohamed posted on 4/6/2016 at 1:51 PM

var fakeEvents = [];
fakeEvents.push(
{
"title":"hello",
"description":"We'll talk about astic, not Ionic.",
"date":incrementDate(new Date(), 5)
}
); like this it work

Comment 56 (In reply to #55) by Messaoud Mohamed posted on 4/6/2016 at 1:52 PM

fakeEvents.push(
{
"title":"hello",
"description":"We'll talk about astic, not Ionic.",
"date":incrementDate(new Date(), 5)
}
);
fakeEvents.push(
{
"title":"Ray's Birthday Bash",
"description":"Celebrate the awesomeness of Ray",
"date":incrementDate(new Date(), 4)
}
);
but over 2 events it dosn't work ?

Comment 57 (In reply to #56) by Raymond Camden posted on 4/6/2016 at 1:54 PM

Do see you see anything in the Chrome remote console?

Comment 58 (In reply to #57) by Messaoud Mohamed posted on 4/6/2016 at 2:07 PM

this all i have

Comment 59 (In reply to #58) by Raymond Camden posted on 4/6/2016 at 2:09 PM

That does not match my code, which means you've modified things a bit. Can you switch back to mine to see if the issue goes away?

Comment 60 (In reply to #59) by Messaoud Mohamed posted on 4/6/2016 at 2:12 PM

i got from the github

Comment 61 (In reply to #60) by Raymond Camden posted on 4/6/2016 at 2:15 PM

Are you sure? The error in the picture shows, "We'll talk about astic, not Ionic". Where do you see that in the GitHub code?

Comment 62 (In reply to #61) by Messaoud Mohamed posted on 4/6/2016 at 2:17 PM

yes i change it to make test

Comment 63 (In reply to #62) by Raymond Camden posted on 4/6/2016 at 2:19 PM

I just asked though if you had modified the code- so can you please do as I suggest and revert your code?

Comment 64 (In reply to #63) by Messaoud Mohamed posted on 4/7/2016 at 10:21 AM

Please the last quetion how can i use this event from data base to chage with the fake please thank you for your help

var eve = this;
$http.get('http://localhost:2480/query/Insta/sql/SELECT * FROM Event', {
headers: { 'Authorization': 'Basic ' + base64('root:root') }}).success(function(response,result) {
//console.log(response.result);
eve.data = response.result;});
console.log(eve);

Comment 65 (In reply to #64) by Messaoud Mohamed posted on 4/7/2016 at 11:49 AM

Please i really need it

Comment 66 (In reply to #64) by Raymond Camden posted on 4/7/2016 at 1:20 PM

Well first off, if you http to localhost, that's the device itself. You need to http to where your server is. If you are testing on your computer itself, it will work, but not when you test on a device of course.

Outside of that, you need to give me a more specific question. You showed code - you didn't say what worked and what didn't.

Comment 67 by Gianfra posted on 4/12/2016 at 8:51 AM

Hi,
Is it possible to add it and see it in the system default calendar ? like this I can get the notification of it

Comment 68 (In reply to #67) by Raymond Camden posted on 4/12/2016 at 11:17 AM

Err, that's what this plugin does. :)

Comment 69 (In reply to #68) by Gianfra posted on 4/12/2016 at 12:29 PM

With the method createEvent i don't see the created event in my calendar and i don't get the notification of it :)

Comment 70 (In reply to #69) by Raymond Camden posted on 4/13/2016 at 7:25 PM

Check the console (with Chrome or Safari Remote Debug) and see if you get an error.

Comment 71 (In reply to #70) by Gianfra posted on 4/14/2016 at 9:41 AM

There was no error, it creates the event but it does not create the notification. I had to use createEventInteractively and create the event on the calendar

Comment 72 (In reply to #71) by Raymond Camden posted on 4/14/2016 at 1:08 PM

Ah. If createEvent is *supposed* to support this and it does not, then I'd file a bug report with the plugin author.

Comment 73 (In reply to #23) by Eniyan posted on 4/17/2016 at 10:11 AM

hellow sir how can i use this code in ionic framework

Comment 74 (In reply to #73) by Raymond Camden posted on 4/18/2016 at 11:53 AM

Um... you know this entire article concerns the Ionic framework, right?

Comment 75 by OneLoud . posted on 5/4/2016 at 6:18 AM

Hi Raymond. I am curious to know if i can call my data from localstorage to your calendar that will be added automatically. I am planning to create android apps which can save data and call them back to calendar as a generate result.

Comment 76 (In reply to #75) by Raymond Camden posted on 5/4/2016 at 1:02 PM

I'm not entirely sure what you are asking. Yes - you can read from LocalStorage and yes - that data could be used with the calendar plugin.

Comment 77 (In reply to #76) by OneLoud . posted on 5/4/2016 at 5:52 PM

Is there a way how to do that? i am new to this stuff (calendar thing).
Let me provide some short story as an example of my problem.

The example story for my problem is like this: "The user fill in the form provided and then all the user input has been saved on the localstorage. Finally, when he/she go to the next scene which is the calendar part, the input that has been saved, will automatically inserted on the calendar based on the user date and time input."

For the date input, i think i make it as a string. I wonder how to make calendar detect my user input data which contain date(from), date(to), time(from), time(to). Please help.

Comment 78 (In reply to #77) by Raymond Camden posted on 5/4/2016 at 7:09 PM

Well first off - do you know how to write and read from LocalStorage?

Comment 79 (In reply to #78) by OneLoud . posted on 5/4/2016 at 7:24 PM

well i do know setItem and getItem for my form. However when it comes to calendar, i got stuck completely. I have 2 main problem, first i'm not sure how to take my user input from localstorage to calendar code. second i have date and time input, and both are string. i wonder how to set the time and date on the calendar based on my input.
To be honest, i never done this before. i do search over an internet but i haven't found any tutorial for addEvent from external input.

Comment 80 (In reply to #79) by Raymond Camden posted on 5/4/2016 at 8:09 PM

"first i'm not sure how to take my user input from localstorage to calendar code."

Well you know how to read from LocalStorage. As for passing it to the calendar code, you know how to do that too - I showed you in the blog post:

$cordovaCalendar.createEvent({
title: event.title,
notes: event.description,
startDate: event.date,
endDate:event.enddate

The values event.tite, event.etc, would be replaced with the values from localestorage.

"second i have date and time input, and both are string."

Try passing them as is.

Comment 81 (In reply to #80) by OneLoud . posted on 5/4/2016 at 8:43 PM

i see. i will work it out. Is it going to work by passing the string date?

Comment 82 (In reply to #47) by Matias A. Urbano posted on 5/4/2016 at 9:02 PM

I have the same problem here. any ideas?

Comment 83 (In reply to #81) by Raymond Camden posted on 5/4/2016 at 9:04 PM

Try it and see.

Comment 84 (In reply to #82) by Raymond Camden posted on 5/4/2016 at 9:11 PM

Um, what I said above?

Comment 85 (In reply to #83) by OneLoud . posted on 5/5/2016 at 8:00 AM

It worked. Never min. i have one last question. for date is new Date() and end Date() right. What about time and day? i want to specify it such as "from 5/5/2016 to 5/31/2016 EVERY Monday". Also from time this to time that. is there a command for this? :)

Comment 86 (In reply to #85) by Raymond Camden posted on 5/5/2016 at 1:40 PM

I honestly don't remember - can you check the docs for the plugin?

Comment 87 (In reply to #86) by OneLoud . posted on 5/5/2016 at 1:55 PM

I did. But so far mostly it mention about date and time format that is relevant with my search.. well i will try look for it again..thanks anyway

Comment 88 by Brock Ellis posted on 7/15/2016 at 4:36 AM

Hey there, Raymond!

This blog post is one of the top resources when searching for Ionic 2 Calendar help, so I wanted to throw this question out there to hear your thoughts.

According to the Calendar plugin author, the plugin isn't threadsafe and its recommended not to call plugin events in a loop. (https://github.com/EddyVerb.... The suggested method is to call a function recursively from within the .then() of the promise that's returned, which kind of sucks since it gets rid of the advantages of the async-ness-itude on the promises.

I've borrowed (almost verbatim...thanks!) your sample code here and it's working great with Ionic 2 on iOS but it dies on Android.

When inspecting the app running on a device, it looks like only a handful of the promises are being resolved and the Promise.all() is never being called.

Just wanted to know if you've heard of anything like this happening or if you would have any advice.

Thanks again for your time!

Comment 89 (In reply to #88) by Raymond Camden posted on 7/15/2016 at 1:33 PM

First off - I had no idea about the threadsafe issue - thank you for letting me know. I'll put it in my queue to update this entry (or probably write a new one and link to it) so folks don't use this version.

If you remote debug w/ Chrome, do you see any exceptions?

Comment 90 (In reply to #89) by Brock Ellis posted on 7/15/2016 at 1:59 PM

I don't see any error in the remote debug session in chrome. Here's the setup I have in my code:


events.forEach(function(ev) {
// do some work up here manipulating start and end date
//title, location, notes, start, end
var x = Calendar.findEvent(ev.Title, null, null, startDate, endDate);
x.then( result => {
console.log("Success!", result);
}, fail => {
console.log("Failed!", fail);
});

promises.push(x);
}

console.log("Promises array");
console.log(promises);

And here is the output I get from the device in the remote console:


> Promises array
> app.bundle.js:810 [ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise, ZoneAwarePromise]
> app.bundle.js:802 Success! []

All of the promises are returned it looks like (13 events and 13 promises in the array) but only one of those promises ever gets resolved. Then the app hangs. It worked perfectly fine when I was testing on an iOS simulator and a real device. I have some log output from running 'adb logcat' that may be relevant, but I'm not quite sure. Still my first rodeo with all of this.

Does anything look out of place? I feel like it's probably something simple I'm missing.

Comment 91 (In reply to #90) by Raymond Camden posted on 7/15/2016 at 2:10 PM

So wait... if the issue is that it isn't threadsafe, then what you have isn't safe either. The code would need to do something like this:

x is an array of events to add
while x isnt empty:
do the add
on done, pop one off X and if crap to do, repeat

Does that pseudo-code change make sense?

Comment 92 (In reply to #91) by Raymond Camden posted on 7/15/2016 at 2:10 PM

Basically the change is to pretend you don't have the easy power of Promises.all anymore. ;)

Comment 93 (In reply to #92) by Brock Ellis posted on 7/15/2016 at 4:36 PM

After a moment of silence for the fallen Promise.all(), I refactored to use a 'threadsafe' method (shamelessly stolen from here.)

Here's what my code looks like now for checking to see if an event exists:



checkEventsExist(events){
//this.events = events;
console.log("Getting to eventsExist and here are the events:");
console.dir(events);

return new Promise( resolve => {
var checkSingleEvent = function (events, i) {
if (i < events.length) {
let event = events[i];
let startDate = Moment.unix(event.Timestamp).toDate();
let endDate = Moment.unix(event.Timestamp).add(1, "day").toDate();

var findingEvent = Calendar.findEvent(event.Title.trim(), undefined, undefined, startDate, endDate);
}else{
console.log("Promise being resolved", events);
resolve(events)

return events;
}

findingEvent.then( status => {
console.log("Status of event " + i + ":" + status);
events[i].Status = status.length === 1;
checkSingleEvent(events, i+1);
}, error => {
console.log("Failed checking single event", error);
});
};

checkSingleEvent(events, 0);
});

}

Still a bit raw, but it seems to work on Android and iOS without too much noticeable lag. Anything obvious that I could improve on? Still a newb at this and would eat up any advice you can give.

Comment 94 by J Santiago AO posted on 10/12/2016 at 4:56 PM

hi, Raymond, i´m working this project on android platform, but when i want to see the app on my device, the app is empty.. i installed correctly the calendar plugin, what is my error?..

Comment 95 (In reply to #94) by Raymond Camden posted on 10/12/2016 at 10:18 PM

When you remote debug, what do you see?

Comment 96 by SENTHIL posted on 10/18/2016 at 7:17 AM

This code is working in iOS fine. But it doesn't work in android. what is my error??

Comment 97 (In reply to #96) by Raymond Camden posted on 10/18/2016 at 2:24 PM

I don't know. :) What do you see when you remote debug w/ Chrome?

Comment 98 by nilanjibamstech posted on 12/15/2016 at 6:27 AM

Hi Raymond: Can I pull data via web service and show the event to this calendar? Is it possible?

Comment 99 (In reply to #98) by Raymond Camden posted on 12/15/2016 at 12:55 PM

Yes. My code has a hard coded list of events - you would just replace that with a service call.

Comment 100 (In reply to #99) by nilanjibamstech posted on 12/15/2016 at 12:58 PM

Thanks.

Comment 101 by William posted on 1/7/2017 at 12:38 AM

Hi every one , can some one explain to me how you can do to run it ? Because I get the GitHub code and try to run it , got an error 'window.plugins is undefined' so I try to install the plugin but didn't find how to , please help me
( ps: sorry for my English I'm French )

Comment 102 (In reply to #101) by Raymond Camden posted on 1/7/2017 at 2:37 PM

Bonjour, you need to make a new Ionic app, then copy my code over into it. It's basically the app source w/o being a real Ionic project - that means I'm storing less files up in GitHub.

Comment 103 (In reply to #102) by William posted on 1/8/2017 at 8:40 PM

It's exactly what I try but got an error "windows.plugin is undefined "

Comment 104 (In reply to #103) by Raymond Camden posted on 1/8/2017 at 8:47 PM

Oh I missed that you said you couldn't install the plugin. You need to. What command did you use to install the plugin?

Comment 105 (In reply to #104) by William posted on 1/9/2017 at 8:53 AM

I quite bit try eveything:

"$ cordova plugin add cordova-plugin-calendar" works ( with cordova plugin ls , the plugin is in the list ) but still error
"$ cordova plugin add https://github.com/EddyVerb..."
this do the same , and with manually instal it call me that $cordova.calendar isn't defined, and angular integer error

Comment 106 (In reply to #105) by Raymond Camden posted on 1/9/2017 at 3:57 PM

So are you testing in the emulator or device?

Comment 107 (In reply to #106) by William posted on 1/9/2017 at 4:00 PM

Yes , unfortunatly there is a blank page with the header bar

Comment 108 (In reply to #107) by Raymond Camden posted on 1/9/2017 at 4:02 PM

And when you remote debug, are you seeing the same error or something different?

Comment 109 (In reply to #108) by William posted on 1/17/2017 at 9:52 AM

Remote debug , how can you do that?

Comment 110 (In reply to #109) by Raymond Camden posted on 1/17/2017 at 12:39 PM

I covered this in multiple articles (go to my About page), and you can also Google for remote debug with Cordova.

Comment 111 by bharathi posted on 5/4/2017 at 11:37 AM

hi ,
can some one explain to me how you can do to run it ?
When i am run this application it showing only heading i.e.,Ionic Calendar Demo
remaining i am not getting

Comment 112 (In reply to #111) by Raymond Camden posted on 5/4/2017 at 11:38 AM

If you don't know how to run Ionic apps, I'd head to their site and go through their documentation. They explain how to get started.

Comment 113 by Bharathi Dasam posted on 5/4/2017 at 11:48 AM

i had created new ionic application and copied your code to my application.when im running on andriod device it showing only heading.please help me

Comment 114 by bharathi posted on 5/4/2017 at 11:49 AM

i had created new ionic application and copied your code to my application.when im running on andriod device it showing only heading.please help me

Comment 115 (In reply to #113) by Raymond Camden posted on 5/4/2017 at 6:22 PM

What do you see when you check the console via remote debug?

Comment 116 (In reply to #114) by Raymond Camden posted on 5/4/2017 at 6:23 PM

I believe you are the same user as below, right?

Comment 117 by Bharathi Dasam posted on 5/5/2017 at 11:03 AM

can anyone tell me how to create push notifications in cordova using visual studio 2015

Comment 118 (In reply to #116) by Bharathi Dasam posted on 5/5/2017 at 11:08 AM

yes same user

Comment 119 (In reply to #117) by Raymond Camden posted on 5/5/2017 at 11:41 AM

This comment has nothing to do with this blog post. For general questions, I'd recommend StackOverflow.

Comment 120 (In reply to #115) by Juan Fernandez Sosa posted on 5/8/2017 at 5:17 PM

be sure to add "cordova-plugin-calendar" into your project.

Comment 121 by terushka posted on 6/11/2017 at 10:44 AM

Are there any chances that need to be made for Ionic 2?

Comment 122 (In reply to #121) by Raymond Camden posted on 6/12/2017 at 2:03 AM

Well, the general principle would be the same, but you couldn't copy and paste as is.

Comment 123 by That Anime Dude posted on 8/18/2017 at 12:41 PM

Great tutorial! I have been searching for one about ionic and google calendar and this is the easiest to follow so far. The only problem i have is that I am using Ionic 2 and some of the stuff has since been deprecated, so I'd really appreciate if you could give me some tips on how I could integrate it into Ionic 2.

Comment 124 (In reply to #123) by Raymond Camden posted on 8/18/2017 at 4:05 PM

In theory, you should be able to use the plugin again, and follow the *form* of my code, but not copy and paste obviously. But what I did you could do in V2 for sure.

Comment 125 (In reply to #124) by Raymond Camden posted on 8/18/2017 at 4:06 PM

And look at the Ionic Native wrapper: https://ionicframework.com/...

Comment 126 (In reply to #125) by That Anime Dude posted on 8/20/2017 at 9:29 AM

Thanks a lot Ray!

Comment 127 by Tinashe | the R posted on 10/20/2017 at 12:36 PM

Hey Ray,
Thanks for the share. Any thoughts on how to dynamically set the startDate and endDate dynamically using JSON - and input the values as a string? I've been struggling with this using Ionic 3x. Thanks.

Comment 128 (In reply to #127) by Raymond Camden posted on 10/21/2017 at 1:30 PM

Well, in theory you would just change where your data comes from. Mine is hard coded, but you could get data from anywhere. Your server, a remote API, etc.

Comment 129 by Kristof De Laet posted on 10/31/2017 at 9:36 AM

Hi Raymond,

First of all, thanks for the nice tutorial.

Could you just confirm one thing for me? This plugin is only for the native calendar, correct?
I'm making an app where I need to access events of a google calendar where users can get an overview of all the events in a specific calendar and can chance there status to attending or not attending for example.
So my question is, can I use this plugin to achieve this and could you give me a tip on how to? If not do you maybe know how to acces the google calendar api in an ionic app? I've been trying do to do so for a long time now and I just can't figure it out :(

Any tips would be highly appreciated,

Thx and keep up the good work!

Comment 130 (In reply to #129) by Raymond Camden posted on 11/4/2017 at 9:52 PM

Native calendar only - but doesn't the OS let you add a Google account and access the calendar? I'd check the docs - I see you can get calendar details - so maybe you can detect a Google calendar, although I'm not sure that makes sense. I mean - the user should have control over where something is stored. It looks like the plugin may be able to get them and show them so you can let the user decide, but I wouldn't force it to a Google calendar specifically.

That being said, Google *does* have APIs for everything, so if the plugin won't work for you, you can roll your own.

Comment 131 by Bradley Wyrosdick posted on 3/15/2019 at 3:43 PM

Is this for Native Ionic apps only or can you use this with Ionic Progressive Web Apps?

Comment 132 (In reply to #131) by Raymond Camden posted on 3/15/2019 at 4:45 PM

PWAs do not have access to their user's calendar. Now - a web app COULD access a Google Calendar and a lot of folks use Google for their calendars, so that would be a possible option. But it wouldn't be the *device* calendar.