Laravel FullCalendar CRUD with Ajax Tutorial

Hello Artisans, today I'll talk about how you can run a CRUD operation on FullCalendar. FullCalendar is very efficient for bookmark your events. You can read more about FullCalendar by clicking here. So, no more talk and dive into topic.

Note: Tested on Laravel 9.0.

Table of Contents

  1. Create Model, Migration and Controller
  2. Modify migration
  3. Modify Model
  4. Modify Controller
  5. Create blade file
  6. Modify Route File
  7. Output

Create Model, Migration and Controller

First of all we need to create Controller where we put our logics, a model for storing data into our database and migration file for our table structure. Fire the below command to create all at a once.

php artisan make:model Event -mcr

Modify migration

Now we already create a event migration file in our step1. Now open it and put the below code in yours

database/migrations/2022_02_20_192332_create_events_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up()
    {
        Schema::create('events', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('start');
            $table->string('end');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('events');
    }
};

Modify Model

Now open the Event.php file which we create in our step1 and the put the below code in yours file.

app/Models/Event.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Event extends Model
{
    use HasFactory;

    protected $fillable = [
        'title',
        'start',
        'end',
    ];
}

Modify Controller

Now open the EventController.php file which we create in our step1 and the paste the below code.

app/Http/Controllers/EventController.php
<?php

namespace App\Http\Controllers;

use App\Models\Event;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;

class EventController extends Controller
{
    public function index(Request $request)
    {
        if ($request->ajax()) {
            $events = Event::all();

            return response()->json($events);
        }

        return view('calendar');
    }

    public function create()
    {
        //
    }

    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required',
            'start' => 'required',
            'end' => 'required'
        ]);

        Event::create($request->all());


        return true;
    }

    public function show(Event $event)
    {
        //
    }

    public function edit(Request $request): \Illuminate\Http\JsonResponse
    {
        $data = [
            'event' => Event::find($request->id),
            'success' => true,
        ];
        return response()->json($data);
    }

    public function update(Request $request, Event $event): \Illuminate\Http\JsonResponse
    {
        $request->validate([
            'title' => 'required',
            'start' => 'required',
            'end' => 'required'
        ]);

        $data = [
            'event' => Event::where('id',$request->id)->update($request->all()),
            'success' => true,
        ];
        return response()->json($data);
    }

    public function destroy(Request $request): \Illuminate\Http\JsonResponse
    {
        $data = [
            'event' => Event::destroy($request->id),
            'success' => true,
        ];
        return response()->json($data);
    }
}

Create Blade File

Now we've to create a blade file for our calendar view, where we can run our CRUD operation in FullCalendar. Create a blade file called calendar.blade.php under resources/views and paste the below code

resources/views/calendar.blade.php
<html>
<head>
    <title>FullCalendar example</title>
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.css"/>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/izitoast/1.4.0/css/iziToast.min.css"/>
</head>
<body>
<div class="container">
    <div class="row m-3">
        <h1>FullCalendar example</h1>
        <hr>
        <div class="col-12">
            <div id='calendar'></div>
        </div>
    </div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/izitoast/1.4.0/js/iziToast.min.js"></script>

<script>
    $(document).ready(function() {

        // pass _token in all ajax
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });

        // initialize calendar in all events
        var calendar = $('#calendar').fullCalendar({
            editable: true,
            events: "{{ route('events.index') }}",
            displayEventTime: true,
            eventRender: function (event, element, view) {
                if (event.allDay === 'true') {
                    event.allDay = true;
                } else {
                    event.allDay = false;
                }
            },
            selectable: true,
            selectHelper: true,
            select: function (start, end, allDay) {
                var event_name = prompt('Event Name:');
                if (event_name) {
                    var start = $.fullCalendar.formatDate(start, "YYYY-MM-DD HH:mm:ss");
                    var end = $.fullCalendar.formatDate(end, "YYYY-MM-DD HH:mm:ss");
                    $.ajax({
                        url: "{{ route('events.store') }}",
                        data: {
                            title: event_name,
                            start: start,
                            end: end
                        },
                        type: 'post',
                        success: function (data) {
                            iziToast.success({
                                position: 'topRight',
                                message: 'Event created successfully.',
                            });

                            calendar.fullCalendar('renderEvent', {
                                id: data.id,
                                title: event_name,
                                start: start,
                                end: end,
                                allDay: allDay
                            }, true);
                            calendar.fullCalendar('unselect');
                        }
                    });
                }
            },
            eventDrop: function (event, delta) {
                var start = $.fullCalendar.formatDate(event.start, "YYYY-MM-DD HH:mm:ss");
                var end = $.fullCalendar.formatDate(event.end, "YYYY-MM-DD HH:mm:ss");

                $.ajax({
                    url: "{{ route('events.edit') }}",
                    data: {
                        title: event.event_name,
                        start: start,
                        end: end,
                        id: event.id,
                    },
                    type: "get",
                    success: function (response) {
                        iziToast.success({
                            position: 'topRight',
                            message: 'Event updated successfully.',
                        });
                    }
                });
            },
            eventClick: function (event) {
                var eventDelete = confirm('Are you sure to remove event?');
                if (eventDelete) {
                    $.ajax({
                        type: "get",
                        url: "{{ route('events.destroy') }}",
                        data: {
                            id: event.id,
                            _method: 'delete',
                        },
                        success: function (response) {
                            calendar.fullCalendar('removeEvents', event.id);
                            iziToast.success({
                                position: 'topRight',
                                message: 'Event removed successfully.',
                            });
                        }
                    });
                }
            }
        });
    });
</script>
</script>
</body>
</html>

Modify Route File

Now we' ve create route for our whole operation. Put the below routes in your web.php

routes/web.php
Route::get('events',[\App\Http\Controllers\EventController::class,'index'])->name('events.index');
Route::post('events/store',[\App\Http\Controllers\EventController::class,'store'])->name('events.store');
Route::get('events/edit',[\App\Http\Controllers\EventController::class,'edit'])->name('events.edit');
Route::get('events/update',[\App\Http\Controllers\EventController::class,'update'])->name('events.update');
Route::get('events/destroy',[\App\Http\Controllers\EventController::class,'destroy'])->name('events.destroy');

Output

We're about to finish our todays' tutorial. If everything goes well, you can visit http://localhost:8000/events and take a look of you own calendar. you can find a below output

FullCalendar Crud with AJAX

That's it for today. Hope you'll enjoy this tutorial. You can also download this from GitHub. Thanks for reading. ๐Ÿ™‚