Fullcalendar is probably the most popular jQuery -based calendar solution, but it does not have an event publishing function. Let’s build this with Laravel and use Bootstrap Modal to modify events without refreshing the page.
See the short video below what the result will look like, our goal is as follows:
- You click on any event in the calendar
- You see that Modal appears with the start / end time to modify
- When you click save in modal, the data must be saved and the event must reappear in the right place in the calendar without refreshing the page
https://www.youtube.com/watch?v=n5a7ponwhne
Let’s start.
Step 1. Preparation: Basic code
As a basic project, we will take our own meeting demo based on QuickadminPanel, but you don’t need to know Quickadminpanel here. The code is quite simple Laravel + blade + jQuery.
Notice: I do not show the full code here, only the parts that are relevant for the calendar.
App / http / controllers / admin / appointment controller.php::
public function index()
{
$appointments = Appointment::all();
return view('admin.appointments.index', compact('appointments'));
}
Resources / views / admin / appointment / index.blade.php::
<link rel="stylesheet" href=" />
<div id='calendar'></div>
<script src="
<script src="
<script>
$(document).ready(function() {
// page is now ready, initialize the calendar...
$('#calendar').fullCalendar({
// put your options and callbacks here
defaultView: 'agendaWeek',
events : [
@foreach($appointments as $appointment)
{
title : '{{ $appointment->client->first_name . ' ' . $appointment->client->last_name }}',
start : '{{ $appointment->start_time }}',
@if ($appointment->finish_time)
end: '{{ $appointment->finish_time }}',
@endif
},
@endforeach
],
});
});
</script>
A few lines of explanation:
- According to the DB structure, the appointment has belonged (customer :: class) relationship;
- Appointment Start_Time And finish_time The fields have a DB date
- We use the Fullcalendar option DefaultView: ‘Agendaweek’ To show the weekly calendar, see other options here
Ok, we have the starting point, let’s start to change the event now.
Step 2. Modify with Bootstrap Modal
At the same time as Resources / views / admin / appointment / index.blade.php File We add this HTML for the modal:
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<h4>Edit Appointment</h4>
Start time:
<br />
<input type="text" class="form-control" name="start_time" id="start_time">
End time:
<br />
<input type="text" class="form-control" name="finish_time" id="finish_time">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="button" class="btn btn-primary" id="appointment_update" value="Save">
</div>
</div>
</div>
</div>
Now we have to call this modal by click on the calendar event. To do this, we add an event to Fullcalendar Javascript called event click.
$('#calendar').fullCalendar({
events : [
@foreach($appointments as $appointment)
{
title : '{{ $appointment->client->first_name . ' ' . $appointment->client->last_name }}',
start : '{{ $appointment->start_time }}',
@if ($appointment->finish_time)
end: '{{ $appointment->finish_time }}',
@endif
},
@endforeach
],
eventClick: function(calEvent, jsEvent, view) {
$('#start_time').val(moment(calEvent.start).format('YYYY-MM-DD HH:mm:ss'));
$('#finish_time').val(moment(calEvent.end).format('YYYY-MM-DD HH:mm:ss'));
$('#editModal').modal();
}
});
Note that we must use the moment.
Thus, at this stage, we show the modal and fill the values โโof the entry field.
Final step – save the changes!
STEP 3. Save changes and reheat the calendar
This part is the most difficult and undocumented in Fullcalendar. Here are some elements that we have to do:
- Create Laravel Route / Controller to update the data
- Call this route from JavaScript and adopt the identification of appointments to update
- Identify the event ID in Fullcalendar (which is different from the database appointment) to delete the old and draw the new update
I found this structure in the roads – just another method within the same controller:
itineraries / web.php::
Route::group(['middleware' => ['auth'], 'prefix' => 'admin', 'as' => 'admin.'], function () {
// ...
Route::resource('appointments', 'Admin\AppointmentsController');
Route::post('appointments_ajax_update',
['uses' => 'Admin\AppointmentsController@ajaxUpdate', 'as' => 'appointments.ajax_update']);
});
App / http / controllers / admin / appointment controller.php::
public function ajaxUpdate(Request $request)
{
$appointment = Appointment::with('client')->findOrFail($request->appointment_id);
$appointment->update($request->all());
return response()->json(['appointment' => $appointment]);
}
So we have to pass the post data in $ requestincluding Rendezvous.id value that should come as $ Request-> appointment_idWe do not currently transmit it to Bootstrap Modal at all.
Also, I do Appointment :: with (‘client’) To be able to draw customer data on the card of a new meeting after update.
Now let’s go our appointment identifier. In addition, we need the Fullcalendar event ID, which is not the same.
To do this, we add these hidden inputs to the Bootstrap modal:
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<input type="hidden" name="event_id" id="event_id" value="" />
<input type="hidden" name="appointment_id" id="appointment_id" value="" />
<div class="modal-body">
...
Then we modify the places in bold in the full call of Fullcalendar:
$('#calendar').fullCalendar({
// put your options and callbacks here
defaultView: 'agendaWeek',
events : [
@foreach($appointments as $appointment)
{
id: '{{ $appointment->id }}',
title : '{{ $appointment->client->first_name . ' ' . $appointment->client->last_name }}',
start : '{{ $appointment->start_time }}',
@if ($appointment->finish_time)
end: '{{ $appointment->finish_time }}',
@endif
},
@endforeach
],
eventClick: function(calEvent, jsEvent, view) {
$('#event_id').val(calEvent._id);
$('#appointment_id').val(calEvent.id);
$('#start_time').val(moment(calEvent.start).format('YYYY-MM-DD HH:mm:ss'));
$('#finish_time').val(moment(calEvent.end).format('YYYY-MM-DD HH:mm:ss'));
$('#editModal').modal();
}
});
You can send the settings you want events Array, they will not be visible nowhere, but you can access it and go to other events. This is what we do with $ appointment-> ID here.
And the internal ID of Fullcalendar of each event is stored in _identifier property of the JavaScript object, we therefore use it as Calevent._id.
The last step is to have a JavaScript method by clicking To safeguard in the modal. We create it outside Fullcalendar, but in the same jQuery block:
Resources / views / admin / appointment / index.blade.php::
$(document).ready(function() {
// ... All the calendar functionality
$('#appointment_update').click(function(e) {
e.preventDefault();
var data = {
_token: '{{ csrf_token() }}',
appointment_id: $('#appointment_id').val(),
start_time: $('#start_time').val(),
finish_time: $('#finish_time').val(),
};
$.post('{{ route('admin.appointments.ajax_update') }}', data, function( result ) {
$('#calendar').fullCalendar('removeEvents', $('#event_id').val());
$('#calendar').fullCalendar('renderEvent', {
title: result.appointment.client.first_name + ' ' + result.appointment.client.last_name,
start: result.appointment.start_time,
end: result.appointment.finish_time
}, true);
$('#editModal').modal('hide');
});
});
});
Step by step, what we do in the block above:
- Forming the data object to be published with current modal values, Including the CSRF token field
- Request a job with this data
- Deletion of the current event in the calendar, using $ (‘# event_id’). Val () value
- Make a new update event in the calendar, using result of the Ajax call
- Bootstrap Modal hiding place
That’s it! May seem quite complicated, but I hope I broke it for you in steps so that you can really use it in your Laravel + JQuery projects.