3

I am trying to include full calendar to my lwc component. I am using 4 version of the calendar. It renders, but eventClick function does not fire. DateClick works as well, but eventClick nope. Firstly, I thought this problem occurred on lwc, then I did it using aura lightning and I have the same problem. Got some message like:

"TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.invokeGetter (:1:142)"

Here is LWC component .html :

<template>
    <div class="fullcalendar" lwc:dom="manual"></div>
</template>

LWC .js :

import { LightningElement } from 'lwc';
import { loadScript, loadStyle} from 'lightning/platformResourceLoader';
import FullCalendarJSs from '@salesforce/resourceUrl/FullCalendarik';

import XSpectr from '@salesforce/resourceUrl/Spectr';
import getCalendarEvents from '@salesforce/apex/CalendarHelper.getCalendarEvents';

export default class FullCalendarJs extends LightningElement {
connectedCallback() {
    Promise.all([
        loadStyle(this, FullCalendarJSs + '/core/main.css'),
        loadScript(this, FullCalendarJSs + '/core/main.js')
    ]).then(() => {
        Promise.all([
            loadStyle(this, FullCalendarJSs + '/daygrid/main.css'),
            loadScript(this, FullCalendarJSs + '/interaction/main.js'),
            loadScript(this, FullCalendarJSs + '/moment/main.js'),
            loadScript(this, FullCalendarJSs + '/daygrid/main.js'),
            loadStyle(this, FullCalendarJSs + '/timegrid/main.css'),
            loadScript(this, FullCalendarJSs + '/timegrid/main.js'),
            loadStyle(this, FullCalendarJSs + '/list/main.css'),
            loadScript(this, FullCalendarJSs + '/list/main.js'),

            loadStyle(this, XSpectr + '/spectre-0.5.8/dist/spectre.min.css')
        ]).then(() => {
            this.initialiseFullCalendar();
        }).catch(error => {
            // eslint-disable-next-line no-console
            console.error({
                message: 'Error on loading core js and css',
                error
            });
        });
    }).catch(error => {
        // eslint-disable-next-line no-console
        console.error({
            message: 'Error occured on FullCalendarJS',
            error
        });
    });
}

initialiseFullCalendar() {
    const ele = this.template.querySelector('div.fullcalendar');
    let calendarEvents = [];
    getCalendarEvents().then(cEvents => {
        JSON.parse(cEvents).forEach(task => {
            calendarEvents.push({
                'id' : task.id, 
                'start' : task.startDate,
                'end' : task.endDate,
                'title' : task.contact.Name + ', Subject : ' + task.subject
            });
        });
        // eslint-disable-next-line no-undef
        let calendar = new FullCalendar.Calendar(ele, {
            plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list', ],
            defaultView: 'dayGridMonth',
            header: {
                left: 'prev,next today',
                center: 'title',
                right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
            },
            height : 650,
            editable: true,
            navLinks: true,
            weekNumbers: true,
            weekNumbersWithinDays: true,
            weekNumberCalculation: 'ISO',
            eventLimit: true,
            selectable: true,
            eventRender: function(info) {
                info.el.setAttribute('data-tooltip', info.event.title);
                info.el.classList.add('tooltip'); 
                function handler() {
                    alert( info.event.title );
                }

                info.el.addEventListener("click", handler);
            },
            dateClick: function(info) {
                // eslint-disable-next-line no-console
                console.log('dateClec : ', info);
            },
            eventClick: function(info) {
                // eslint-disable-next-line no-console
                console.log('eventClick : ', info);
            },
            events: calendarEvents
        });
        calendar.render();
    }).catch();
}
}

And i fixed two methods in core/main.js (it on 104 line):

var matchesMethod = function (el, selector) {
    var matches = document.querySelectorAll(selector);
    var th = this;
    return Array.prototype.some.call(matches, function(el) {
        return el === th;
    });
};
var closestMethod = function (selector) {
    // polyfill
    var el = this;
    if (!document.documentElement.contains(el)) {
        return null;
    }
    do {
        if (elementMatches(el, selector)) {
            return el;
        }
        el = el.parentElement || el.parentNode;
    } while (el !== null && el.nodeType === 1);
    return null;
};
function elementClosest(el, selector) {
    return closestMethod.call(el, selector);
}
function elementMatches(el, selector) {
    return matchesMethod.call(el, selector);
}

Apex Class to get data:

public with sharing class CalendarHelper {
    @AuraEnabled
    public static String getCalendarEvents(){
        Map<Id, Contact> idsToContacts = new Map<ID, Contact>([SELECT Id, Name FROM Contact]);
        List<CalendarEventWrapper> tasks = new List<CalendarEventWrapper>();
        for (Task task : [SELECT Id, WhoId, ActivityDate, Subject FROM Task]) {
            tasks.add(new CalendarEventWrapper( task.Id, 
                                                idsToContacts.get(task.WhoId),
                                                task.ActivityDate,
                                                task.Subject ));
        }
        for (Event event : [SELECT Id, WhoId, StartDateTime, EndDateTime, Subject FROM Event]) {
            tasks.add(new CalendarEventWrapper( event.Id, 
                                                idsToContacts.get(event.WhoId),
                                                event.StartDateTime,
                                                event.EndDateTime,
                                                event.Subject ));
        }
        return JSON.serialize(tasks);
    }

    public class CalendarEventWrapper {
        Id id;
        Contact contact;
        DateTime startDate;
        DateTime endDate;
        String subject;

        public CalendarEventWrapper(Id id, Contact contact, DateTime startDate, String subject) {
            this.id = id;
            this.contact = contact;
            this.startDate = startDate;
            this.subject = subject;
        }

        public CalendarEventWrapper(Id id, Contact contact, DateTime startDate, DateTime endDate, String subject) {
            this.id = id;
            this.contact = contact;
            this.startDate = startDate;
            this.endDate = endDate;
            this.subject = subject;
        }
    }
}
  • 1
    This is due to locker services in lightning preventing it .would you mind posting code from which one can reproduce the issue ? – Mohith Shrivastava Dec 18 '19 at 7:52
  • 1
    @MohithShrivastava posted code here. – programmer-228 Dec 18 '19 at 8:02
  • @programmer-228 I got stuck with the same problem which landed me on your question. I'm curious did you get it to work in the end and if so, could you post the fix? – POZ Jan 29 at 8:22
  • 1
    @POZ i've posted the answer below – programmer-228 Jan 29 at 8:44
  • 1
    It works great, thanks for sharing that. It was real pain. – POZ Jan 29 at 9:04
4

Here is an answer: Fix methods in core/main.js

 var matchesMethod = Element.prototype.matches ||
    Element.prototype.matchesSelector ||
    Element.prototype.msMatchesSelector;
var closestMethod = Element.prototype.closest || function (selector) {
    var el = this;
    if (!document.documentElement.contains(el)) {
        return null;
    }
    do {
        if (elementMatches(el, selector)) {
            return el;
        }
        el = el.parentElement || el.parentNode;
    } while (el !== null && el.nodeType === 1);
    return null;
};
function elementClosest(el, selector) {
    if (!el.closest) {
        if (!document.documentElement.contains(el)) {
            return null;
        }
        do {
            if (elementMatches(el, selector)) {
                return el;
            }
            el = el.parentElement || el.parentNode;
        } while (el !== null && el.nodeType === 1);
        return null;
    }
    else
        return el.closest(selector);
}
function elementMatches(el, selector) {
    if (!el.matches)
        return el.msMatchesSelector(selector);
    else
        return el.matches(selector);
}
|improve this answer|||||
  • 1
    Kudos to you for fixing/amending the FullCalendar core library! – Robs Mar 18 at 21:43
-2

Try this, i did it and it's working:

var matchesMethod = function ( selector) {
    var matches = document.querySelectorAll(selector);
    var th = this;
    var aux2 = false;
    for (var i = 0; i < matches.length; i++) {
      if(aux2 == false)
          aux2 = matches[i] === th; 
    }
    return aux2;
};
var closestMethod = function (selector) {
    // polyfill
    var el = this;
    if (!document.documentElement.contains(el)) {
        return null;
    }
    do {
        if (elementMatches(el, selector)) {
            return el;
        }
        el = el.parentElement || el.parentNode;
    } while (el !== null && el.nodeType === 1);
    return null;
};
function elementClosest(el, selector) {
    return closestMethod.call(el, selector);
}
function elementMatches(el, selector) {
    return matchesMethod.call(el, selector);
}
|improve this answer|||||
  • This didn't fix the eventClick event not being fired. – POZ Jan 29 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.