Skip to content

Instantly share code, notes, and snippets.

@sjurgis
Last active February 5, 2018 08:37
Show Gist options
  • Save sjurgis/3c9ad1294b1466d7b910 to your computer and use it in GitHub Desktop.
Save sjurgis/3c9ad1294b1466d7b910 to your computer and use it in GitHub Desktop.
FullCalendar calendar view implementation in Salesforce.com

This is an adaptation of Cody Sechelski's Create a Calendar View in Salesforce.com.

The main problem with his implementation was that it wasn't handling more than 2000 records. This was due to a Apex workaround, as it is reserves start and end variables, Cody made a repeat table and parsed that into JavaScript object. My solution creates JSON string in Apex and then uses string function to replace all startString and endString instances. A more sensible solution would involve recreating the object in JavaScript or simply editing the FullCalendar library to look for different variable names.

I have also simplified the code a bit so you can start working towards your personal implementation. As this is using JavaScript remoting, I hope this gives you a framework to work towards more advanced features like editing or optimizing request sizes (executing a request on next month load).

The page

<apex:page showHeader="false" standardStylesheets="false" controller="fullCalendar" >
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"/>
    <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.3/moment.min.js"/>
    <script src="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.3.1/fullcalendar.min.js"/>
    <link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.3.1/fullcalendar.min.css" rel="stylesheet" />
    <link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.3.1/fullcalendar.print.css" rel="stylesheet" media="print"  />
    <body>             
   <script type="text/javascript"> 
      function getEventData() {                         // records are retrieved from soql database
        Visualforce.remoting.Manager.invokeAction(
            '{!$RemoteAction.fullCalendar.eventdata}',  // controller and method names
            function(result, event){
                if (event.status) {
                    evt =  JSON.parse(result);
                    $('#calendar').fullCalendar({       // html element and library name
                        events: evt                     
                    }) 
                } else if (event.type === 'exception') { 
                    console.log(event.message);
                } else {
                    console.log(event.message);
                }
            }, 
            {escape: false}
        );
    }
    $(document).ready(function() {
        getEventData();
    });
    </script>
    <div id="calendar"></div>
    </body>
</apex:page>

The class

public class fullCalendar {
    public string eventsJSON {get;set;}
    
    //The calendar plugin is expecting dates is a certain format. We can use this string to get it formated correctly
    static String dtFormat = 'EEE, d MMM yyyy HH:mm:ss z';

    @RemoteAction
    public static string eventdata(){
        calEvent[] events = new calEvent[]{};
        for(Event evnt: [select Id, Subject, isAllDayEvent, StartDateTime, EndDateTime from Event]){
            DateTime startDT = evnt.StartDateTime;
            DateTime endDT = evnt.EndDateTime;
            
            calEvent myEvent = new calEvent();
            myEvent.title = evnt.Subject;
            myEvent.allDay = evnt.isAllDayEvent;
            myEvent.startString = startDT.format(dtFormat);
            myEvent.endString = endDT.format(dtFormat);
            myEvent.url = '/' + evnt.Id;
            myEvent.className = 'event-personal';
            events.add(myEvent);
        }
        
        string jsonEvents = JSON.serialize(events);
        jsonEvents = jsonEvents.replace('startString','start');
        jsonEvents = jsonEvents.replace('endString','end');
        
        return jsonEvents;
    }

    // Class to hold calendar event data
    public class calEvent {
        public String title {get;set;}
        public Boolean allDay {get;set;}
        public String startString {get;set;}
        public String endString {get;set;}
        public String url {get;set;}
        public String className {get;set;}
    }
}

Tested to 10'000 records with this execute anonymous

event[] bulklist= new event[]{};
for (integer i = 0; i < 100000; i++)
{
    string srnd = string.valueOf(math.random());
    blob rnd = Blob.valueOf(srnd);
    bulklist.add(new event (
        subject=encodingUtil.base64Encode(rnd),
        startDateTime=system.now().addDays(-10+ (math.random() * 10 ).intValue()),
        isAllDayEvent=true     
    ) );
}
insert bulklist;

To do: test with natural distribution graph.

@mkonyk
Copy link

mkonyk commented Aug 12, 2016

Hi, thank you for sharing!
The string format for Date that you gave us above is correct, but in some cases it might be an issues when events don not display in Calendar because of GMT.
To fix that just use formatGmt() method instead of format() method when you are setting Start and End Date of Event.

@Nelson9206-zz
Copy link

Hi Guys

Could someone please assist me in having this setup in my org. I have tried copying the above code but nothing seems to be displaying. I am new to javascript, perhaps I am not doing something right. Can someone please send me a full sample based on the aforementioned tutorial. It seems dated so I am not sure if it still works the same.

Kind Regards

@beccig
Copy link

beccig commented Jun 26, 2017

Hello,

I have implemented this solution and it is populating great. But how do you call a refetch or refresh when there are changes? I have tried several things and nothing will make it go out to the controller and get a new JSON list to populate. It just populates the same thing.

Thank you for you help. I have been trying for 3 months and currently just refresh the entire page with a submit button. It works but does not bring the user back to the page they were on.

@beccig
Copy link

beccig commented Jul 20, 2017

Hello,
I'm still looking for help on this to be able to refetch event. Any help is appreciated :-).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment