2

EDIT: Range is now structures correctly as an array and dates and times are now formatted as ISO8601. Unfortunately same error message on console with hasTime.


I am trying to make a school timetable using FullCalendar, loading each lesson from a database using php to encode to json.

I am trying to show each lesson recurring weekly on the timetable only within the dates of the semester (2016/09/26 - 2016/12/16) This range might be different for other lessons.

Below is the output of the EventListRecurring.php

   [{
    "id": "1",
    "title": "History",
    "start": "09:00",
    "end": "10:00",
    "dow": "1",
    "ranges": [{
        "start": "2016-09-26",
        "end": "2016-12-16"
    }],
    "allDay": false
}, {
    "id": "2",
    "title": "English",
    "start": "10:00",
    "end": "12:00",
    "dow": "2",
    "ranges": [{
        "start": "2016-09-26",
        "end": "2016-12-16"
    }],
    "allDay": false
}, {
    "id": "3",
    "title": "Geography",
    "start": "14:00",
    "end": "16:00",
    "dow": "3",
    "ranges": [{
        "start": "2016-09-26",
        "end": "2016-12-16"
    }],
    "allDay": false
}]

I have tried using slicedtoads solution with the following javascript but there are no events on the calendar and getting only get this error

CalendarTimetableRecurring

<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<link rel='stylesheet' href='fullcalendar/fullcalendar.min.css' />
<script src='fullcalendar/lib/jquery.min.js'></script>
<script src='fullcalendar/lib/moment.min.js'></script>
<script src='fullcalendar/fullcalendar.js'></script>
</head>
<body>
<h1>Reapeating Events Example </h1>
<div id='calendar'></div>

<script type="text/javascript">
var repeatingEvents = 
    'EventListRecurring.php'

var getEvents = function( start, end ){
    return repeatingEvents;
}

$('#calendar').fullCalendar({
    defaultDate: moment(),
    header: {
        left: 'prev,next today',
        center: 'title',
        right: 'month,agendaWeek,agendaDay'
    },
    defaultView: 'month',
    eventRender: function(event, element, view){
        console.log(event.start.format());
        return (event.ranges.filter(function(range){
            return (event.start.isBefore(range.end) &&
                    event.end.isAfter(range.start));
        }).length)>0;
    },
    events: function( start, end, timezone, callback ){
        var events = getEvents(start,end);

        callback(events);
    },
});


</script>   
</body>
</html>

EventListRecurring.php

<?php

$record[0]["title"]="History";
$record[1]["title"]="English";
$record[2]["title"]="Geography";

$record[0]["start_time"]="09:00";
$record[1]["start_time"]="10:00";
$record[2]["start_time"]="14:00";

$record[0]["end_time"]="10:00";
$record[1]["end_time"]="12:00";
$record[2]["end_time"]="16:00";

$record[0]["dow"]="1";
$record[1]["dow"]="2";
$record[2]["dow"]="3";

$record[0]["start_date"]="2016-09-26";
$record[1]["start_date"]="2016-09-26";
$record[2]["start_date"]="2016-09-26";

$record[0]["end_date"]="2016-12-16";
$record[1]["end_date"]="2016-12-16";
$record[2]["end_date"]="2016-12-16";

$record[0]["id"]="1";
$record[1]["id"]="2";
$record[2]["id"]="3";

for ($i=0; $i<3; $i++) {

    $event_array[] = array(
            'id' => $record[$i]['id'],
            'title' => $record[$i]['title'],
            'start' => $record[$i]['start_time'],
            'end' => $record[$i]['end_time'],
            'dow' => $record[$i]['dow'],
            'ranges' => array(
                0 => array(
                    'start' => $record[$i]['start_date'],
                    'end' => $record[$i]['end_date'],
                )
            ),
            'allDay' => false

    );


}

echo json_encode($event_array);


exit;

?>
Community
  • 1
  • 1
Michael
  • 251
  • 3
  • 11
  • in your EventListRecurring.php your end time seems inappropriate, try adding time like you did in start. – Saurav Dangol Feb 22 '17 at 13:38
  • typo with end date and end time in php script. Fixed now but issue is still the same. I updated the code and included a screenshot of the console error message. – Michael Feb 22 '17 at 15:01

1 Answers1

1

Your "ranges" property is not structured the same way as in the solution you linked to. You're returning a single object, not an array:

"ranges": {
    "start": "2016-09-26",
    "end": "2016-12-16"
}

should be

"ranges": [{
    "start": "2016-09-26",
    "end": "2016-12-16"
}]

Once you fix this, your code seems to run fine and work as expected.

You can amend your PHP as follows to create this structure:

'ranges' => array(
    0 => array(
        'start' => $record[$i]['start_date'],
        'end' => $record[$i]['end_date'],
    )
)

Lastly, amend your data source definition to:

events: "EventListRecurring.php"

The way you're doing it now, with a custom data source, is unnecessary because you aren't manipulating the data, and also won't work because you would have to handle the ajax call yourself - currently it's just returning a string containing the name of your PHP script. It isn't actually calling that script.

ADyson
  • 57,178
  • 14
  • 51
  • 63
  • I have added my EventListRecurring.php above. 'ranges' => array( 'start' => $record[$i]['start_date'], 'end' => $record[$i]['end_date'], ), Is this where my error is? – Michael Feb 23 '17 at 21:29
  • yeah that's the problem. You're only outputting one object (although you defined an array, json_encode will make it an object because it's got non-sequential indexes). What you want is in array inside an object. So for that you need an outer array with a single numeric index (so it comes out as an array in JSON) which contains the array which will form a single "range" object. Edited the answer to give you an example (not tested, but hopefully works, you get the idea etc!) – ADyson Feb 24 '17 at 09:44
  • Thanks for the help. Unfortunately same error "cannot read property 'hasTime' of undefined" I have updated the code with the range now correctly as an array and dates/times in ISO8601 format. – Michael Feb 24 '17 at 16:03
  • which line is causing the "hasTime is undefined" error? I can't see what line 41 is in your page. BTW I don't think those date strings are in a compliant format. Have a look at http://momentjs.com/docs/#/parsing/string/ for compliant ISO8601 formats. "090000000" doesn't appear to match any of those, as far as I can see. If it's a number, then you need to remove the quotes around it, and then it indicates milliseconds since the UNIX epoch and resolves to 1970-02-01 01:00:00. e.g. try `var m = moment(090000000); console.log(m.format("DD/MM/YYYY HH:mm:ss"));` Not sure if you intended that? – ADyson Feb 24 '17 at 16:49
  • I meant 09:00am. have changed it back to '09.00". Line 41 of CalendarTimetableRecurring.html is 'callback(events);' – Michael Feb 24 '17 at 18:28
  • As far as I can see, you need to specify your range dates in yyyy-mm-dd format as well (rather than yyyymmdd). Working example here: http://jsfiddle.net/smwtdLfp/1/ . If you change the dates to yyyymmdd the events stop appearing where they should. Not sure why - that format supposedly is accepted by moment, but you get a parse warning, so clearly it isn't. – ADyson Feb 27 '17 at 10:05
  • Changed dates to yyyy-mm-dd (as shown above) and same error message with "cannot read property 'hasTime' of undefined". As JSFiddle is working perfectly could it be an issue with ** events: function( start, end, timezone, callback ){ var events = getEvents(start,end); ** – Michael Feb 27 '17 at 11:34
  • yes. I think you're just returning the string "EventListRecurring.php" instead of having it actually call the data source. Try simply specifying `events: "EventListRecurring.php"` in your fullCalendar method. You don't need a custom data source definition for this as far as I can see, because you aren't manipulating the event data on the client before you send it to the callback. – ADyson Feb 27 '17 at 11:41
  • P.S. If you _do_ specify a custom data source, like now, then you have to create all the ajax code yourself. Hence why it's just returning the string with the name of your PHP script, not the server data. If you do as I've just suggested, fullCalendar does it all for you. It even passes relevant start/end dates in, so that your server-side can only load the data required for the current view. Once you move to having custom data instead of hard-coded, this will be useful. See https://fullcalendar.io/docs/event_data/events_json_feed/ for an example of what gets passed to the server. – ADyson Feb 27 '17 at 11:44
  • 1
    That's it working now. Thanks for help, additional information and persistence! – Michael Feb 27 '17 at 11:49