0

I have a div, where I want to show the calendar based on button click:

<label class="btn" onclick="getCalendar();"> Show Calendar </label>

<div id="calendarDiv">

</div>

The getCalendar() function is implemented as following:

function getCalendar() {
    var calendar = new FullCalendar.Calendar($("#calendarDiv"), {
        plugins: ['dayGrid'],
        header: {
            left: 'title',
            center: '',
            right: 'today prev,next'
        },
        buttonText: {
            today: 'Today'
        },

        defaultView: 'dayGridMonth',
        defaultDate: '2019-09-12',

        events: function(fetchInfo, successCallback, failureCallback) {
            $.post('/Customer/GetCalendarEvents',
                $.param({
                        selectedCountryIds: getSelectionsByName('cntName'),
                        fiscalYearEnd: '31/12/2018'
                    },
                    true),
                function (res) {
                    var events = [];
                    console.log(res);
                    $.each(res,
                        function (index, value) {
                            events.push({
                                title: value.title,
                                start: value.start
                            });
                        });
                    successCallback(events);
                })
                .fail(function () {
                failureCallback(alert('bla')); 
            });
        }
    });
    calendar.render();
}

Where, the GetCalendarEvents(selectedCountryIds, fiscalYearEnd) returns a Json array with a list of events that is constructed as following:

public JsonResult GetCalendarEvents(List<int> selectedCountryIds, string fiscalYearEnd) {
    // some initial steps to get finalList
    // creating result array
    var result = finalList.Select(r => new
    {
        title = r.Item2 + " : " + r.Item3,
        start = r.Item1
    });
    return Json(result, JsonRequestBehavior.AllowGet);
}

The function returns correct array and the events[] is properly generated, however, when I run it I get nothing shown and in console I see an error:

main.min.js:6 Uncaught TypeError: e.addEventListener is not a function
    at O (main.min.js:6)
    at e.bindHandlers (main.min.js:6)
    at e.render (main.min.js:6)
    at getCalendar (ViewName:1118) // this is the line with calendar.render();
    at HTMLLabelElement.onclick (ViewName:1037)

Any suggestions what can be an issue and how could I resolve it? I am using the latest version of FullCalendar.

1
  • try $("#calendarDiv")[0] Commented Sep 13, 2019 at 7:59

2 Answers 2

2

It looks like the problem is that $("#calendarDiv") returns a jQuery object, but the fullCalendar constructor expects a native DOM element.

You could write $("#calendarDiv")[0] to extract the DOM element from the jQuery object (as suggested in one of the comments), but it's kind of pointless to create a jQuery object just so you can throw it away again immediately.

Instead just use a native selector:

var calendar = new FullCalendar.Calendar(document.querySelector("#calendarDiv"), {

P.S. I think you could simplify your events code a lot. This code stood out to me initially:

events.push({
  title: value.title,
  start: value.start
}); 

It's unclear why you are recreating an object which has an identical structure to the original? You will get output which is exactly the same as the input!

If the server is already outputting the JSON in the right format, then you can use the simpler events as JSON feed pattern to connect your events to fullCalendar. You just give fullCalendar the URL and the basic parameters and it will take care of the rest:

events: {
  url: '/Customer/GetCalendarEvents',
  method: "POST",
  extraParams: function() { // a function that returns an object
    return {
      selectedCountryIds: getSelectionsByName('cntName'),
      fiscalYearEnd: '31/12/2018'
    };
  }
}
6
  • getElementById is better supported than querySelector. Everything else is a perfect answer Upvote :P Commented Sep 13, 2019 at 8:46
  • @angel.bonev Thanks, but out of interest, where is a problem with support for querySelector do you think? developer.mozilla.org/en-US/docs/Web/API/Document/… indicates very wide support across different browsers and versions. Have you got a specific example?
    – ADyson
    Commented Sep 13, 2019 at 9:07
  • document.querySelector support vs document.getElementById is part of DOM since level 1 so it's supported in all browsers if you test it its 51% faster benchmark Commented Sep 13, 2019 at 9:50
  • @angel.bonev ok but in terms of support, no-one cares anymore about those ancient browsers which supported it from day one. And performance benchmarking is not the same as support for the syntax. It does seem you get a noticeable performance increase at scale using getElementById. But then again in the real world no-one selects 10000 elements at once. If you just select one, the difference is negligible. You might expect querySelector to be slightly slower though, since it can select by more than just an ID if you want it to. I think for this purpose it's a moot point, but thanks.
    – ADyson
    Commented Sep 13, 2019 at 10:10
  • 1
    @angel.bonev in general that's a reasonable approach but in this case realistically there's no worthwhile difference in support unless you really are required to support something like IE7, but these days that would be highly unusual.
    – ADyson
    Commented Sep 13, 2019 at 10:28
1

As you can see in the official docs you need to pass Element , but in you code $("#calendarDiv") jquery will return array-like object of Elements read mode here, so if you need to use jquery selector you can get it like this $("#calendarDiv")[0] or you can do it like the suggest in the official docs

 var calendar = new FullCalendar.Calendar(document.getElementById('calendar'), { ... 
1
  • 1
    "jquery will return array of Elements" ...technically it will return a jQuery object, which is a lot more than just an array. The link you've provided explains that, in fact. But what's the point of creating a jQuery object, putting the DOM element in it, and then immediately discarding it again just to get the native DOM element? the jQuery constructor is a relatively complex and expensive thing. Better not to waste the browser's time, and just use a native selector method e.g. document.getElementById or document.querySelector. jQuery is just a pointless overhead here
    – ADyson
    Commented Sep 13, 2019 at 8:36

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