nativescript

Importing iCal (*.ics) Feed into the UI for NativeScript Calendar Component

52 VIEWS

I encountered a requirement while implementing a mobile application recently where I needed to display events in a mobile application that are published on a Google Calendar. I could have gone the route of using a WebView and embedding it that way, but I wanted the users to experience the richness and beauty of using a fully native application.

I decided to utilize the UI for NativeScript from Progress Software, a professional grade component library that is available free of charge. Included in this offering is a Calendar component that satisfies my need for a better user experience.

Note: this is expecting that you already have the module importing the UI for NativeScript Calendar and ListView components. It is also importing only basic iCal data, no recurrence rule parsing is taking place. This article also doesn’t step you through creating a NativeScript application from scratch, it shows you how to add the functionality into an existing module. In this case, I have created an application module called Calendar, and I have already setup the module, routes, etc.

Obtain the calendar feed

The first thing that you will need is the public or private feed for the Google Calendar that you’d like to have imported to have displayed in the NativeScript Calendar component. To do this, open your Google Calendar page, on the upper-right hand corner of the page, click on cog icon and select ‘Settings’.


Google Calendar Settings

Next, ensure you select the correct calendar to edit the settings for. Then scroll toward the bottom of the settings window, and find the iCal address. You can choose a public link (for published calendars) or the private link for private/unpublished calendars. In my case, the calendar is not public, so I am making a note of the private iCal address.


iCal Addresses

Establishing a model

In order to populate the Calendar component, it requires data to adhere to the CalendarEvent model established in the API. This model includes the following properties:

  1. endDate
  2. eventColor
  3. isAllDay
  4. startDate
  5. title

This is a great model for a base calendar, however, I need a little more information captured in my events, so I created a new class that extends the CalendarEvent model – adding to it a couple more properties. Here is a listing of my app/models/calendar-event-extended.ts file:

Creating a service class

I have my project setup to have service classes to retrieve data from Firebase Firestore or any other external data source. This is where I will put my class that is responsible for pulling, parsing and transforming the iCal data into the CalendarEventExtended structure. Here is a listing of my services/calendar-service.ts file:

From the code above, you can see that I am pulling the iCal data from a url and parsing its content. This is only providing basic parsing, I don’t have logic in there to deal with recurrence rules, so this will work in the basic calendar usage case. I am also utilizing the trace module for logging functionality, so if you are not using that – it can be removed. The getCalendarEventsPromise function returns just that, a promise that it will retrieve, parse, and transform the calendar data into an array of CalendarEventExtended objects.

Establishing a View Model

In this application, what I needed to do is display the calendar with events, then when a date is selected, to list the events for that date in a list below the calendar (I am also using the ListView component from UI from NativeScript). This View Model is also responsible for setting styles for the calendar, most of which I retained as the defaults. You will notice that I am importing another service, application-service – this is where I have set things like the iCal url as well as the color palette for the application. The listing for view-models/calendar-view-model.ts is as follows:

From the code above, you can see that I am using MomentJS and the extensions available in Moment-Range packages – both are available via npm. You can also see that I’ve created an event onDateSelected that will filter events by the date selected – these will be displayed in the ListView.

Date Formatting Display Pipe

In my list view, I also wanted to format the dates and times in a specific format, as such I created a simple DateTimeFormatter pipe to transform my data to the desired format. This formatter must be in your @NgModule declaration in order to use it. The source code for the pipes/dateTimeFormatter.ts is as follows:

Finally – the view!

The component code for my application Calendar module utilizes another plug-in for displaying the events list as a series of cards. I am also using the angular drawer navigation template as the basis of my application. My component source file listing is as follows (app/calendar/calendar.component.ts):

From the code above, you can see that it utilizes the service that was created to pull back data and populate the view model.

The view listing is as follows (calendar.component.html):

Here is what the resulting code looks like on a device:


UI for NativeScript Calendar

Wrap-up

One of the nice things about NativeScript is its flexibility. I like that I am easily able to extend it using JavaScript and leverage many of the helper libraries available on NPM to get me where I need to go. This is just a simple example of how you can provide an in-application native experience to your users while still using information you’ve already got published on the web.

Do you think you can beat this Sweet post?

If so, you may have what it takes to become a Sweetcode contributor... Learn More.

Carey Payette is a Senior Software Engineer with Trillium Innovations, as well as an ASPInsider and Progress Developer Expert. She has an interest in IoT and is a member of the Maker community. Carey is also a wife and mom to three fabulous boys. She has a 2nd degree black belt in TaeKwonDo and enjoys coding for fun!


Discussion

Click on a tab to select how you'd like to leave your comment

Leave a Comment

Your email address will not be published. Required fields are marked *

Menu