DEV Community

samanthamarberger
samanthamarberger

Posted on

Enhancing Event Management with FullCalendar in React Rails

Struggling with event management in your React Rails app? Discover how FullCalendar can simplify the process!

Event management can be such a hassle when creating applications that require scheduling. It is important for the users of your application to have visual representation of current appointments and future bookings. A user-friendly calendar component allows for easy user scheduling or editing for anything that involves a date and time.

FullCalendar is a JavaScript library that can be used in your Rails/ React applications. It is a powerful and customizable solution for handling event management within our applications.

Basics of a React Rails Application

React Rails applications are simple and powerful to use. Allowing you to have front and back-end functionality in the same place saves time and space. The simplicity through associations in Rails and the ease of React and components allow for an efficient development experience.

React components are great for the separation of concerns, and you can pass variables and functions through the use of state and props between components. This keeps your code clean, organized, and easy to debug.

React Rails Application

I am going to assume that you already have your React Rails application up and running with your models built and ready to go. Using a recent project of mine, I have an application where a trainer can post their availability and the clients can then book on those postings. I am going to show the Trainer side of posting/ editing/ deleting availabilities. My simplified models and migrations look like this:

The Availability Model:

class Availability < ApplicationRecord
    belongs_to :trainer
end

Enter fullscreen mode Exit fullscreen mode

Migration:

class CreateAvailabilities < ActiveRecord::Migration[6.1]
  def change
    create_table :availabilities do |t|
      t.integer :trainer_id
      t.datetime :start
      t.datetime :end

      t.timestamps
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

The Trainer Model:

class Trainer < ApplicationRecord
    has_many :availabilities
end
Enter fullscreen mode Exit fullscreen mode

Migration:

class CreateTrainers < ActiveRecord::Migration[6.1]
  def change
    create_table :trainers do |t|
      t.string :name

      t.timestamps
    end
  end
end

Enter fullscreen mode Exit fullscreen mode

Now that we have these associations in place, we know that the relationship between Trainer and Availabilities is a one to many allowing for easy access within our application.

Installing and Configuring FullCalendar

To install FullCalendar, type into your terminal

npm install --save @fullcalendar/react
Enter fullscreen mode Exit fullscreen mode

We will also need 3 FullCalendar Plug-ins to make our Calendar more interactive. Type into the terminal

npm install --save @fullcalendar/daygrid @fullcalendar/timegrid @fullcalendar/interaction
Enter fullscreen mode Exit fullscreen mode

With everything installed, we need to import the plug-ins to our react parent components. Let's create a component called Calendar. It should look like this

import React from "react";
import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import interactionPlugin from '@fullcalendar/interaction';


function Calendar() {

}

Enter fullscreen mode Exit fullscreen mode

With our plug-ins imported and our component initialized, we can now add functionality.
Let's start with rendering our Calendar on the page and allow the user to select between day, week, and month views, as well as the previous, next, and today buttons.

function Calendar() {
    return (
        <div className="calendar">
            <FullCalendar 
            initialView='dayGridMonth'
            headerToolbar={{
                left: "prev,next,today",
                center: "title",
                right: "dayGridMonth,timeGridWeek,timeGridDay"
            }}
            plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
            />
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

I have set the initial view to dayGridMonth so that when the Calendar is initially rendered, you are looking at a month calendar view; however, the default can be set to day or week.

If you look at your calendar you should see something like this:
Image description

Now that we have a simple and clean calendar that the user can toggle through, let's add some functionality!

So that I can see the events I want to schedule, I have to add an events variable that will take in events as props.

events={events}
Enter fullscreen mode Exit fullscreen mode

That simple bit of code will allow me to view the events passed in. Next let's add a callback prop that will allow me to click on the calendar and perform the callback function passed in.

selectable={true}
eventClick={eventClick}
Enter fullscreen mode Exit fullscreen mode

You want to set selectable to true if you have any interaction with the calendar, whether that be to schedule, edit, or even to get a pop-up view. We are not able to click an event, but what if we want to pass in a callback that will allow us to select a date?

dateClick={dateClick}
Enter fullscreen mode Exit fullscreen mode

Easy enough! Let's see what this looks like all together, don't forget to pass in the callback function props for Calendar to put to use.

function Calendar({ events, eventClick, dateClick }) {

    return (
        <div className="calendar">
            <FullCalendar 
            initialView='dayGridMonth'
            headerToolbar={{
                left: "prev,next,today",
                center: "title",
                right: "dayGridMonth,timeGridWeek,timeGridDay"
            }}
            plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
            events={events}
            selectable={true}
            eventClick={eventClick}
            dateClick={dateClick}
            />
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Great! We now have a calendar that the user can interact with. Let's put it to use.

We want an Availabilities component where a trainer can interact with the calendar. First step, we make sure to import our Calendar into the Availabilities component. From here we can set our events that we will pass to the calendar.

const availabilities = user.availabilities.map(a => ({
        title: `Availability`,
        start: a.start,
        end: a.end,
        availability_id: a.id,
    }))
Enter fullscreen mode Exit fullscreen mode

These availabilities will be passed as the events and displayed on the calendar, I am using seed data for this.

We now want to build a callback that we can send to Calendar to schedule appointments. I would create a form that the user can fill in start and end times, and on submission, send it to the back end create action in the availabilities controller. This is what that submission callback, addAvailability, will look like.

    const [selectedDate, setSelectedDate] = useState([])
    const handleDateClick = (info) => {
        setSelectedDate(info.dateStr)
    }
    const [start, setStart] = useState(`${selectedDate}T11:00`)
    const [end, setEnd] = useState(`${selectedDate}T12:00`)

    function handleSubmit(e) {
        e.preventDefault()
        addAvailability({
            start: start,
            end: end
        })
    }
Enter fullscreen mode Exit fullscreen mode

I have the times set to default but using a form, the user can change that. Now that I have events and a callback function I can return a calendar that visualizes the availabilities and allows for user interaction.

import Calendar from "./Calendar";

function Availabilities() {
    const [selectedDate, setSelectedDate] = useState([])
    const handleDateClick = (info) => {
        setSelectedDate(info.dateStr)
        setCreateModalOpen(true)
    }
    const [start, setStart] = useState(`${selectedDate}T11:00`)
    const [end, setEnd] = useState(`${selectedDate}T12:00`)

    function handleSubmit(e) {
        e.preventDefault()
        addAvailability({
            start: start,
            end: end
        })
    }

    const availabilities = user.availabilities.map(a => ({
        title: `Availability`,
        start: a.start,
        end: a.end,
        availability_id: a.id,
    }))


        return (
            <div>
                <Calendar
                    events={availabilities}
                    dateClick={handleDateClick}
                />
            </div>
        )
    }
    else {
        return <h1>Error: Not Authorized</h1>
    }
}

Enter fullscreen mode Exit fullscreen mode

Remember, I have a form that on submission creates and posts the new Availabilities, but with those additions, my Calendar now looks like this!

Image description

How great is that! We now have a component that can be used for all different scenarios through the use of callback functions as props.

This is a great tool because it allows you to continue using Rails in the way you already know how, but have a much easier and interactive user interface. There are so many ways you can customize your Calendars, be sure to check out Full Calendar's official docs for more great ways to customize.

In conclusion, incorporating FullCalendar into your Rails/React applications provides a powerful and customizable solution for managing events, appointments, and schedules. The seamless integration of React components with Rails associations offers an efficient development experience, allowing for the creation of user-friendly and interactive calendars.

By following the step-by-step instructions for installing and configuring FullCalendar, we've demonstrated how to create a dynamic and responsive calendar component. Whether you're building a scheduling system, managing appointments, or handling event bookings, FullCalendar's flexibility allows for customization to suit various use cases.

Incorporate these practices into your Rails React projects, and empower your users with an intuitive and engaging event management experience. Feel free to share your thoughts, experiences, and any challenges you encounter in the comments. Happy coding!

Top comments (0)