SpaceAge
SpaceAge

Reputation: 91

FullCalendar v3 - Change Event Source on View Change

I'm using FullCalendar v3 (latest) with a PHP backend.

I'm returning a JSON array from the backend broken up into 2 arrays. The first contains event details (a list of orders for the day, with the order# as the title), and the second contains a daily summary (with a sum of orders and work hours as the title). The array looks like this:

{"events":[{"id":709989,"item_no":"ABC123","title":709989,"color":"red","start":"2019-05-14","end":"2019-05-14","allDay":true,"total_hours":3,"remaining_hours":1.5},{"id":709990,"title":709990,"item_no":"ABC345","color":"red","start":"2019-05-15","end":"2019-05-15","allDay":true,"total_hours":5.7,"remaining_hours":3.2}],"summary":[{"id":338823,"title":"Orders: 14\rHours:28.33\rRemaining Hours:13.33","start":"2019-05-14","end":"2019-05-14","allDay":true},{"id":338824,"title":"Orders: 3\rHours:14.2\rRemaining Hours: 12.2","start":"2019-05-15","end":"2019-05-15","allDay":true}]}

There are other properties but these are the basics.

What I'm trying to do is change the array that's used as the event source depending upon which view is selected. I've tried custom event rendering, custom view rendering, multiple event sources (even though it's expensive from a data point-of-view, the # of records aren't so numerous that it greatly effects performance).

The custom view name is customMonth. When this view is selected, I just want to render the summary data (from the summary array). If any of the other views are selected (I'm using basicWeek, month and listWeek), render the events array.

let vname;
$("#calendar").fullCalendar({
    defaultDate: new Date(),
    defaultView: 'month',
    eventRender: function(eventObj, $el, view) {
        let n = view.name;
        if(n=='customMonth')
        {
            vname = 'customMonth';
            $el.popover({
                title: eventObj.title,
                content: eventObj.total_hours,
                html: true,
                trigger: 'hover',
                placement: 'auto',
                container: 'body'
            });
        } else {
            vname = n;
            $el.popover({
                title: "Work Order " + eventObj.title,
                content: '<strong>Item#</strong>: ' + eventObj.item_no + '<br />' + '<strong>Total Hours</strong>: ' + eventObj.total_hours + '<br />' + '<strong>Remaining Hours</strong>: ' + eventObj.remaining_hours,
                html: true,
                trigger: 'hover',
                placement: 'auto',
                container: 'body'
            });
        }
    }, 
    events: function(start, end, timezone, callback){
        $.ajax({
            url: '/myendpoint',
            type: 'POST',
            dataType: 'json',
            data: {
                action: 'get-calendar-summary',
                cell: selected_cell
            },
            success: function(data) {
                let events = [];
                if(vname=='customMonth') {
                    obj = data.summary;
                    $(obj).each(function() {
                        events.push({
                            id: $(this).attr('id'),
                            title: $(this).attr('title'),
                            start: $(this).attr('dept_due_dt'),
                            end: $(this).attr('dept_due_dt'),
                            total_hours: $(this).attr('total_hours'),
                            remaining_hours: $(this).attr('remaining_hours'),
                            order_count: $(this).attr('day_order_count'),
                            has_late_order: $(this).attr('has_late_order'),
                            allDay: true,
                            earliest_date: $(this).attr('earliest_date')
                        });
                    });
                } else {
                    obj = data.event_results;
                    $(obj).each(function() {
                        events.push({
                            id: $(this).attr('id'),
                            color: $(this).attr('color'),
                            title: $(this).attr('title'),
                            start: $(this).attr('start'),
                            end: $(this).attr('end'),
                            earliest_date: $(this).attr('earliest_date'),
                            item_no: $(this).attr('item_no'),
                            total_hours: $(this).attr('total_hours'),
                            remaining_hours: $(this).attr('remaining_hours')
                        });
                    });
                }
                callback(events);
            },
            error: function(err) {
                console.log(err);
            }
        });
    },
    views: {
        customMonth: {
            type: 'month',
            buttonText: 'overview'
        }
    },
    viewRender: function(view, el) {
        let lastview;
        if(view.name=='customMonth') {
            if(lastview == 'customMonth') {
                return false;
            } else {
                view.unrenderDates();
                view.renderDates();
                $("#calendar").fullCalendar('rerenderEvents');
            }
            lastview = 'customMonth';
        } else {
            if(lastview=='customMonth') {
                view.unrenderDates();
                view.renderDates();
                $("#calendar").fullCalendar('rerenderEvents');
            }
            lastview = view.name;
        }
    },
    header: {
        left: 'prev,next',
        center: 'title',
        right: 'basicWeek,month,listWeek,customMonth'
    },
    themeSystem: 'bootstrap3',
    timeZone: false,
    weekends: false,
    //tried with and without lazyFetching
    lazyFetching: true
});

I'd appreciate any guidance. I've searched StackOverflow (this seems like the closest, but I followed exactly and it didn't work (switching out viewDisplay for viewRender)), Github, and all other sources I can think of.

Upvotes: 2

Views: 1984

Answers (1)

Ugo T.
Ugo T.

Reputation: 1078

Here a simplified example of what you are trying to achieve (I hope I well understand your problem) :

HTML :

 <div id='calendar'></div>

Javascript :

$(document).ready(function() {
    var ev1 = {"events":[{"id":709989,"item_no":"ABC123","title":'Event from source 1',"color":"red","start":"2019-05-14","end":"2019-05-14","allDay":true,"total_hours":3,"remaining_hours":1.5}]};
    var ev2 = {"events":[{"id":709989,"item_no":"ABC123","title":'Event from source 2',"color":"blue","start":"2019-05-14","end":"2019-05-14","allDay":true,"total_hours":3,"remaining_hours":1.5}]};
    $('#calendar').fullCalendar({
        defaultDate: new Date(),
        defaultView: 'month',
        viewRender: function(view) {
          if(view.type === 'basicWeek') {
             $('#calendar').fullCalendar( 'removeEventSource', ev1 );
             $('#calendar').fullCalendar( 'addEventSource', ev2 );
             return; 
           }  
        },
        header: {
           left: 'prev,next',
           center: 'title',
           right: 'basicWeek,month,listWeek,customMonth'
        },

    });
    $('#calendar').fullCalendar( 'addEventSource', ev1 );  
});

And the codepen to try it.

It uses the callback function viewRender() to detect when a view change and addEventSource()/removeEventSource() to change the data. So when you change the view from month to week it will change the source events.

Upvotes: 3

Related Questions