Fancy calendars for your web application with FullCalendar

While working on a project, I had the need of adding some calendars to display information from events already saved …

While working on a project, I had the need of adding some calendars to display information from events already saved on a RoR application. Fortunately, I had done something similar for a project during my last semester of college using a fantastic Javascript library called FullCalendar created by Adam Shaw.

In this blogpost, I'll guide you through the process of integrating the calendar with an existent Ruby on Rails application by using one of the new features that comes included with Rails 4 by default: jbuilder

Hands on

We are going to create a simple Rails 4 app to demonstrate the integration but, if you already have an application that needs a calendar, this example will also help you. That is because the 'magic' that glues together the calendar with our application lies on what jbuilder does: creating a JSON response

Let's create an scaffold for a model called 'Event' with some attributes to display in our calendar:

rails generate scaffold Event title:string description:text start_time:datetime end_time:datetime

And don't forget to run migrations and run the server:

rake db:migrate
rails server

Now that we are ready, we can navigate to localhost:3000/events and see our brand new event list.

image alt

We can see the JSON representation of our events by going to localhost:3000/events.json

image alt

Setting up the calendar

We can download the necessary assets from the FullCalendar webpage or using the FullCalendar-rails gem. In case that you, as me, prefer to use it as a gem, we only need to add it our Gemfile

gem 'fullcalendar-rails'

And then run

bundle install

At this point, the files are already in the assets pipeline's path and the final step is to require them in our application.* files:

In application.css.scss we'll add

*= require fullcalendar

And in our application.js

//= require fullcalendar

In order to feed our calendar, we need to create some events either from the web interface created by the scaffold or using the Rails console: I will leave this part up to you.

We need to create a div in our view and initialize the calendar using jQuery:

$('#calendar').fullCalendar();

And we have our fullCalendar up and running:

image alt

Note: I made it smaller using CSS: by default, the calendar takes all the width available

Let's move to the backend

Now that our calendar looks awesome, we need to work on how the events are going to be displayed and, yes, it is time to move on to Rails.

There are many ways to load our events in the calendar but the most interesting and useful for this example is to provide the calendar with a URL where it can get the events as a JSON array. This array will look similar to this:

    [
        {
            title  : 'event1',
            start  : '2010-01-01'
        },
        {
            title  : 'event2',
            start  : '2010-01-05',
            end    : '2010-01-07'
        },
        {
            title  : 'event3',
            start  : '2010-01-09 12:30:00',
            allDay : false
        }
    ] 

We need to make sure to return our JSON according to this format, this is where jbuilder will help us.

The JSON way

The scaffold we used to generate the application has already provided us with a handy way of adding JSON support: we can take a look at app/views/events/index.json.builder file and see the default format it provides:

json.array!(@events) do |event|
  json.extract! event, :id, :title, :description, :start_time, :end_time
  json.url event_url(event, format: :json)
end

It just takes all the events and its attributes and creates an array. We can see the output by visiting localhost:3000/events.json

image alt

So close! It looks very similar to the format fullCalendar expects but we need to make a couple of changes to make it match:

json.array!(@events) do |event|
  json.extract! event, :id, :title, :description
  json.start event.start_time
  json.end event.end_time
  json.url event_url(event, format: :html)
end

We had to rename the start\time_ and end\time_ to start and end.

Additionally, we changed the format of the URL attribute from :json to :html. I'll explain this in the next step.

Our new output will look similar to this:

image alt

When frontend meets backend

Now that our backend provides us with a JSON response in the same format that fullCalendar needs, we need to go back where we initialized our fullCalendar and send the proper params:

$('#calendar').fullCalendar(
    events: '/events.json'
);

And we are done! now our calendar shows the events we have added:

image alt

Remember the change we did in the index.json.builder file about pointing our URL attribute to its HTML version instead of the JSON one? We'll, this change allows us to point to our '/events/{id}.html' route when we click on an event.

Wrapping up

It is worth to notice that you are not tied to using jbuilder for creating the JSON response: you can use ActiveModel::Serializer, Rabl or whatever that fits your application needs… or even better, you could use fullCalendar without RoR, another framework or even a different language might work. The key for the integration is to follow the JSON format that fullCalendar requires.

I really encourage you to read the documentation to know about all the customization that fullCalendar supports: it is a very flexible and powerful library and I bet you don't want to miss all the options it provides.

Finally, you can take a look at this example in this github repository specially created for this blogpost.

Thanks for reading!

Keep reading

More >