I have json format events available on a "/ index" url. I would like to be able to retrieve them in order to display them on the calendar. I followed the official tutorial to the letter but unfortunately I still can't do it, here are my files:
calendar.js
$(function () {
'use strict'
// Initialize fullCalendar
$('#calendar').fullCalendar({
height: 'parent',
locale: 'fr',
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay,listWeek'
},
navLinks: true,
selectable: true,
selectLongPressDelay: 100,
editable: true,
nowIndicator: true,
defaultView: 'listMonth',
views: {
agenda: {
columnHeaderHtml: function (mom) {
return '<span>' + mom.format('ddd') + '</span>' +
'<span>' + mom.format('DD') + '</span>';
}
},
day: {
columnHeader: false
},
listMonth: {
listDayFormat: 'ddd DD',
listDayAltFormat: false
},
listWeek: {
listDayFormat: 'ddd DD',
listDayAltFormat: false
},
agendaThreeDay: {
type: 'agenda',
duration: {
days: 3
},
titleFormat: 'MMMM YYYY'
}
},
events: "/index",
eventAfterAllRender: function (view) {
if (view.name === 'listMonth' || view.name === 'listWeek') {
var dates = view.el.find('.fc-list-heading-main');
dates.each(function () {
var text = $(this).text().split(' ');
var now = moment().format('DD');
$(this).html(text[0] + '<span>' + text[1] + '</span>');
if (now === text[1]) {
$(this).addClass('now');
}
});
}
console.log(view.el);
},
eventRender: function (event, element) {
if (event.description) {
element.find('.fc-list-item-title').append('<span class="fc-desc">' + event.description + '</span>');
element.find('.fc-content').append('<span class="fc-desc">' + event.description + '</span>');
}
var eBorderColor = (event.source.borderColor) ? event.source.borderColor : event.borderColor;
element.find('.fc-list-item-time').css({
color: eBorderColor,
borderColor: eBorderColor
});
element.find('.fc-list-item-title').css({
borderColor: eBorderColor
});
element.css('borderLeftColor', eBorderColor);
},
});
var calendar = $('#calendar').fullCalendar('getCalendar');
// change view to week when in tablet
if (window.matchMedia('(min-width: 576px)').matches) {
calendar.changeView('agendaWeek');
}
// change view to month when in desktop
if (window.matchMedia('(min-width: 992px)').matches) {
calendar.changeView('month');
}
// change view based in viewport width when resize is detected
calendar.option('windowResize', function (view) {
if (view.name === 'listWeek') {
if (window.matchMedia('(min-width: 992px)').matches) {
calendar.changeView('month');
} else {
calendar.changeView('listWeek');
}
}
});
// Display calendar event modal
calendar.on('eventClick', function (calEvent, jsEvent, view) {
var modal = $('#modalCalendarEvent');
modal.modal('show');
modal.find('.event-title').text(calEvent.title);
if (calEvent.description) {
modal.find('.event-desc').text(calEvent.description);
modal.find('.event-desc').prev().removeClass('d-none');
} else {
modal.find('.event-desc').text('');
modal.find('.event-desc').prev().addClass('d-none');
}
modal.find('.event-start-date').text(moment(calEvent.start).format('LLL'));
modal.find('.event-end-date').text(moment(calEvent.end).format('LLL'));
//styling
modal.find('.modal-header').css('backgroundColor', (calEvent.source.borderColor) ? calEvent.source.borderColor : calEvent.borderColor);
});
//display current date
var dateNow = calendar.getDate();
calendar.option('select', function (startDate, endDate) {
$('#modalCreateEvent').modal('show');
$('#eventStartDate').val(startDate.format('LL'));
$('#eventEndDate').val(endDate.format('LL'));
$('#eventStartTime').val('07:00:00').trigger('change');
$('#eventEndTime').val('10:00:00').trigger('change');
});
$('.select2-modal').select2({
minimumResultsForSearch: Infinity,
dropdownCssClass: 'select2-dropdown-modal',
});
$('.calendar-add').on('click', function (e) {
e.preventDefault()
$('#modalCreateEvent').modal('show');
});
})
web.php (laravel)
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
/* Courses Routes */
Route::post('admin/calendar', 'CoursesController@store')->name('courses.store');
Route::get('index', 'CoursesController@index');
Result when I do a request on "/ index", this is the result:
{
"backgroundColor": "rgba(91,71,251,.2)",
"borderColor": "#5b47fb",
"events": [{
"start": "2020-10-07T07:00:00",
"end": "2020-10-07T10:00:00",
"title": "statistiques",
"description": "drink Coffee"
}]
};
Here is the class "Coursescontroller" which manages everything
<?php
namespace App\Http\Controllers;
use App\Courses;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use App\Http\Resources\CourseResource;
class CoursesController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth:admin');
}
/**
* retrieve the data from the "courses" table
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$course = DB::select('select * from courses where universityReference = ?', [Auth::user()->universityReference]);
//let's select the first line
$data = [
"backgroundColor" => $course[0]->backgroundColor,
"borderColor" => $course[0]->borderColor,
"events" => [unserialize($course[0]->events)]
];
return array($data);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* transform the raw data collected, in order to properly format them for recording
*
*/
public function composeCourseData($arg)
{
//convert dates into ISODATE format ('Y-m-d')
$convertStartDate = date('Y-m-d', strtotime(str_replace('-', '/', $arg->input('startDate'))));
$convertEndDate = date('Y-m-d', strtotime(str_replace('-', '/', $arg->input('endDate'))));
//convert times into ISOTIME format (H:M:S)
$convertStartTime = strftime('%H:%M:%S', strtotime($arg->input('startTime')));
$convertEndTime = strftime('%H:%M:%S', strtotime($arg->input('endTime')));
//final datetime output
$outputStartDate = "".$convertStartDate."T".$convertStartTime."" ;
$outputEndDate = "".$convertEndDate."T".$convertEndTime."" ;
//array to store course basic informations
$courseData = array(
'courseToken' => Str::random(23,'alphaNum'),
'creatorReference' => Auth::user()->reference,
'professorName' => $arg->input('professorName'),
'location' => $arg->input('location'),
'start' => $outputStartDate,
'end' => $outputEndDate,
'title' => $arg->input('subject'),
'description' => "".$arg->input('type')." '".$arg->input('subject')."' en ".$arg->input('location')." du ".$arg->input('professorName')." avec les etudiants de ".$arg->input('studyYear')." annee (".$arg->input('faculty').")",
);
//serialize course data before saving in db;
return serialize($courseData);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//Validate informations
/*$course = request()->validate([
/*'professorName'=>'required|string'
'subject'=> 'string|required',
'location'=>'required',
'start'=>'required',
'end'=>'required',
'description'=>'string'
]);*/
/* switch to determine the type of event (course, homework, tutorials or exams)
* in order to assign a color
* */
switch ($request->input('type')) {
case 'examens':
$ok = Courses::create([
//think about how to externalize this part of the code which is repeated almost 4 times
'universityReference' => Auth::user()->universityReference,
'creatorReference' => Auth::user()->reference,
'type' => $arg->input('type'),
'faculty' => $arg->input('faculty'),
'studyYear' => $arg->input('studyYear'),
//green
'backgroundColor' => 'rgba(16,183,89,.25)',
'borderColor' => '#10b759',
'events' => $this->composeCourseData($request)
]);
break;
case 'TD':
Courses::create([
//orange
'universityReference' => Auth::user()->universityReference,
'creatorReference' => Auth::user()->reference,
'type' => $request->input('type'),
'faculty' => $request->input('faculty'),
'studyYear' => $request->input('studyYear'),
'backgroundColor' => 'rgba(253,126,20,.25)',
'borderColor' => '#fd7e14',
'events' => $this->composeCourseData($request)
]);
break;
case 'devoirs':
Courses::create([
//pink
'universityReference' => Auth::user()->universityReference,
'creatorReference' => Auth::user()->reference,
'type' => $request->input('type'),
'faculty' => $request->input('faculty'),
'studyYear' => $request->input('studyYear'),
'backgroundColor' => 'rgba(241,0,117,.25)',
'borderColor' => '#f10075',
'events' => $this->composeCourseData($request)
]);
break;
default:
Courses::create([
//purple
'universityReference' => Auth::user()->universityReference,
'creatorReference' => Auth::user()->reference,
'type' => $request->input('type'),
'faculty' => $request->input('faculty'),
'studyYear' => $request->input('studyYear'),
'backgroundColor' => 'rgba(91,71,251,.2)',
'borderColor' => '#5b47fb',
'events' => $this->composeCourseData($request)
]);
break;
}
return redirect()->route('admin.app.calendar');
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Courses $course)
{
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Courses $course)
{
$course->delete();
return response('Course removed successfuly !', Response::HTTP_NO_CONTENT);
}
}
I know this is not the satandard use but, i would like to retrieve events in this format, is that possible?
because: I save all the events of the same type ($ request-> input ('type') as (exams or TD ..), in a single "events" array that I store with a precise backgroundColor and borderColor. Every time an event of this same "type" tries to be saved, I just modify the corresponding line by editing the "events" array.
{
backgroundColor: 'rgba(253,126,20,.25)',
borderColor: '#fd7e14',
events: [{
id: '16',
start: '2020-10-07T07:00:00',
end: '2020-10-07T07:00:00',
title: 'My Rest Day'
},
{
id: '17',
start: '2020-10-07T07:00:00',
end: '2020-10-08T11:00:00',
title: 'My Rest Day'
}
]
}
The structure of the JSON being generated by your PHP code not compatible with fullCalendar. It must be a plain array of events, with no outer structure around it.
e.g. it should output this kind of structure
only.
To do that you need to amend your PHP as follows. I've included the background and border colours still, but they need to be appended to each event object individually: