How do I show and/or hide events using CSS in FullCalendar?

471 Views Asked by At

Although I'm an experienced programmer, I can't say I'm a JavaScript expert and also just started trying to grasp the ins and outs of FullCalendar. So I apologize beforehand for not yet grasping all the aspects yet, not having found everything in the docs yet and not always using the proper terminology.

In my particular case the events are being loaded from a JSON feed. Using checkboxes, I want to show and/or hide events based on their extendedProps.type. In order to prevent unnecessary round trips to the server, I prefer to load all types of events at once and add/remove classes to/from the the event elements, allowing me to show or hide them in a maintainable manner, using CSS. This turns out to be harder than I anticipated.

The first challenge was adding checkboxes to the toolbar. Unfortunately FullCalendar does not seem to have an easy, standard way of adding additional rows to the toolbar. Similarly there appears to be no way to add anything other than regular <button> type interaction elements. So I ended up using a <template> tag to add an extra element to the toolbar and some additional flexbox tweaks.

The hard part turns out to be the showing and hiding of events. Important to know is my intent to make the initial visibility state to be configurable. My initial thought was to add an invisible class and style it with display: none. The obvious place to add the class seems to be the eventDidMount hook. This appears to work at first; after the initial render some events are visible and some are not. However, when trying to show the invisible events, nothing seems to happen. Analysis of the problem shows that FullCalendar adds a visibility: invisible to the parent element of the event, when the event element is set to display: none.

Not an expert on these matters, my solution was changing the display: none into a visibility: invisible. Now the initially invisible events show up when toggling their visibility, but there is another problem: the invisible events do take up space. So month views show day cells with a lot of empty space and list views show rows without data.

The first thing I could think of, was some sort of after event render hook, in which I could add a display: none to the invisible elements. After searching through documentation and stackoverflow issues, I concluded their is no such thing. Some stackoverflow topics seem to provide a solution at first glance, but then turn out to make use of legacy methods or hooks, which are no longer supported.

The second thing I could think of, was counting the number of mounted events, compare them with the number of loaded events and once all events are mounted, assuming space would have been allocated for the events, add an additional class to invisible events, allowing me to set a display: none in my style sheet. A very hacky construction, to say the least. What makes it even more hacky, is the fact that I can not find an easy way to get hold of the number of events loaded. So I ended up with ugly stuff, resetting a counter to zero in the loading hook and adding the number of loaded events in the eventSourceSuccess hook. Maybe the initial reset is not necessary, but I don't know for sure how many times the eventSourceSuccess hook gets triggered.

Unfortunately this also did not solve the problem. Apparently, 'mounted' does not mean 'added to the DOM and space allocated'. At least not in the way I expect, that visibility: invisible still shows up on the event's parent element :(

Getting this far took me many hours and a combination of disappointment and frustration and I still have no adequate solution. The lack of some sort of 'after all events rendered' hook feels like a real shortcoming, as well as a simple way to obtain the total number events loaded. More handles to customize the toolbar would be a great improvement as well.

I'm stuck. That might well be because I missed or misunderstood things in the documentation and on stackoverflow. Hopefully someone can help me out and point me in the right direction for some or all of the issues I encountered.

Thanks in advance.

1

There are 1 best solutions below

0
On

I realised that I approached the show/hide challenge all wrong. Trying to achieve it using CSS is not the right way. Considering complications that might arise from multi day events for instance, maybe I should have realised that right from the start.

After some more digging and searching, I found out how it can be done using event sources. Most helpful was a proposed solution from Andy, answering another stackoverflow question: Is it possible to Remove EventSources and add them back dynamically based on View Name?. By simply using different event sources for different event types, adding and removing them on request, it's actually quite easy to toggle visibility of event types. The only drawback seems to be that multiple API request are needed, one per event source. Maybe a solution for that is hidden somewhere as well, which I love to hear about.