stefanuebe/vaadin-fullcalendar

setEntryDidMountCallback doesn't work with Java 11

Closed this issue · 21 comments

Bug Description

On the wiki, in "Customize the entry content" : https://github.com/stefanuebe/vaadin_fullcalendar/wiki/FullCalendar-Examples#customize-the-entry-content
There is an example with a setEntryContentCallback function that return info.el
But for event content, there isn't a el element, from the docs :
image

Example Code

I'm using v4.1.2
I tried to use the example from the javadoc, with no success, the content stay empty :

calendar.setEntryContentCallback("" +
     "function(arg) { " +
     "  let italicEl = document.createElement('i');" +
     "  if (arg.event.getCustomProperty('isUrgent', false)) {" +
     "    italicEl.innerHTML = 'urgent event';" +
     "  } else {" +
     "    italicEl.innerHTML = 'normal event';" +
     "  }" +
     "  let arrayOfDomNodes = [ italicEl ];" +
     "  return { domNodes: arrayOfDomNodes }" +
     "}");

The only way I found to edit the content, is editing event._def.title.
But it doesn't look like it's the right way to do it

I tried to use setEntryDidMountCallback but looks like it never get in the function (no log found in console) :

calendar.setEntryDidMountCallback("" +
                "function(info) {" +
                "   console.log('----');" +
    	        "   console.log(info);" +
    	        "   console.log('----');" +
                " info.el.style.color = 'red';" +
                " return info.el; " +
                "}"
        );

Did I forget something or something ?
What does the setEntryContentCallback function really need as return ?

Hi,
the setEntryContentCallback is correct but as you pointed out is not for edit the event content. You can do it editing event._def.title . The setEntryDidMountCallback is for edit the content as in the example, it call eventDidMount .

eventDidMount - called right after the element has been added to the DOM. If the event data changes, this is NOT called again.

Are you sure you are correctly adding the event to the calendar?

Hi @aetasoul ! Thanks for your answer.

the setEntryContentCallback is correct but as you pointed out is not for edit the event content

So, what does the example (from javadoc) do ? I think it creates and return a <i>urgent/normal event</i> but it doesn't add anything for me.

Are you sure you are correctly adding the event to the calendar?

I think so, I'm using calendar.setEntryProvider(EntryProvider.lazyInMemoryItems(entries)); with entries a list of ResourceEntry.
Should I use another provider ?

Hi,
<i>urgent/normal event</i> is inserted inside the inner-most wrapper of the event element.

It's ok to use calendar.setEntryProvider(EntryProvider.lazyInMemoryItems(entries));, just be sure the variable entries contains the events you want to display. Do you see them on the calendar when it render?

Can you provide your Vaadin version? There is no error in the dev console?
I'll try to test it

Unfortunately, I don't see the <i> tag when I'm using the setEntryContentCallback. Here's my DOM of the event :

<div class="fc-timegrid-event-harness fc-timegrid-event-harness-inset" style="inset: 55px 0% -271px; z-index: 1;">
   <a class="fc-timegrid-event fc-v-event fc-event fc-event-draggable fc-event-resizable fc-event-start fc-event-end fc-event-past fc-event-today" style="border-color: cyan; background-color: cyan;" tabindex="0">
      <div class="fc-event-main" style="color: black;">
         <div class="fc-event-main-frame">
            <div class="fc-event-time">08:00 - 12:00</div>
            <div class="fc-event-title-container">
               <div class="fc-event-title fc-sticky">CHEQUE</div>
            </div>
         </div>
      </div>
      <div class="fc-event-resizer fc-event-resizer-end"></div>
   </a>
</div>

Do you see them on the calendar when it render?

Yes I do :
image

Can you provide your Vaadin version? There is no error in the dev console?

I'm using Vaadin 14.8.10 and no error on dev console 😕

Thanks for your time !

I'll check it as soon as possible

I can't reproduce the problem, I tried to replicate it for 2 days, but it works all the time.

  1. Create a basic instance of the calendar
  2. Create a single entry and add it to the calendar (With EntryProvider.lazyInMemoryItems)
  3. add calendar.setEntryDidMountCallback that print hello in the dev console as console.log('hello');
  4. add calendar.setEntryContentCallback that print aaaaaa in the dev console as console.log('aaaaaa');
  5. All works fine

Can you share a minimal reproducible example?

Try to study this example about the setEntryContentCallback (I tried it and works fine)

I don't know why you don't see the console.log output on you console, anyway you can't set the text color from the el, after the last update of the calendar the implemented a property for the event to do this. You can do it like this: entry.setTextColor("red"); from the server side so you don't need the setEntryDidMountCallback.

Thanks again for your time !

Can you share a minimal reproducible example?
Try to study this example about the setEntryContentCallback (I tried it and works fine)

Well, I copy pasted exactly the example you gave (I understand how it works, with custom property etc), I added a setEntryDidMountCallback that print "hello", but same thing, it doesn't appear.

The only reason I need setEntryDidMountCallback is for appending diffrents icons.

I'll try with a fresh vaadin starter, and see if the problem is not from my project. Indeed, for any addons I installed, I have to inject the @NpmPackage(...) and @JsModule(...) in my main AppLayout, so the add-on can appear and work.. it may be related but I don't know how

Unfortunately, it's the same thing with a fresh project :(

  1. I downloaded the quick start project there
  2. Add the addons, and the example
  3. Run the app
  4. Still nothing from setEntryDidMountCallback

Here's the callback function I added :

calendar.setEntryDidMountCallback("" +
    "function (info) {" +
    "    console.log('---- hello');" +
    "}");
calendar.setEntryContentCallback("" +
    "function (info) {" +
    "    console.log('---- aaaaa');" +
    "    console.log(info);" +
    "    info.backgroundColor = info.event.getCustomProperty('selected', false) ? 'lightblue' : 'lightgreen';" +
    "}");

and the console logs when I get to home page :

Setting heartbeat interval to 300sec. client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
Scheduling heartbeat in 300 seconds client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:213:20
Starting application ROOT-2521314 client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
Vaadin application servlet version: 2.7.15 client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
Handling message from server client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:1036:622
Handling dependencies client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:979:50
StateTree after applying changes: client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:997:127
Object { pushConfiguration: {…}, elementData: {…}, clientDelegateHandlers: [], polymerServerEventHandlers: [], elementListeners: {…}, synchronizedPropertyEvents: [], virtualChildrenList: [], elementChildren: (1) […], classList: [] }
client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
handleUIDLMessage: 1 ms client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightblue", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
---- aaaaa vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:37
Object { event: {…}, view: {…}, timeText: "12a", textColor: "", backgroundColor: "lightgreen", borderColor: "lightgreen", isDraggable: true, isStartResizable: false, isEndResizable: false, isMirror: false, … }
vaadin-bundle-7ba24506f8c64665ac28.cache.js line 1136 > eval line 759 > Function:3:67
First response processed 1908 ms after fetchStart client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
 Processing time was 367ms client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
Sending xhr message to server: {"csrfToken":"f13f0934-434b-44f7-9f84-150bb6a77c7e","rpc":[{"type":"publishedEventHandler","node":3,"templateEventMethodName":"setBrowserTimezone","templateEventMethodArgs":["Europe/Paris"],"promise":0},{"type":"event","node":3,"event":"datesSet","data":{"event.detail":{"name":"dayGridMonth","intervalStart":"2022-11-01","intervalEnd":"2022-12-01","start":"2022-10-31","end":"2022-12-12"}}},{"type":"event","node":3,"event":"datesSet","data":{"event.detail":{"name":"dayGridMonth","intervalStart":"2022-11-01","intervalEnd":"2022-12-01","start":"2022-10-30","end":"2022-12-11"}}}],"syncId":0,"clientId":0} client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
Server visit took 91ms client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
JSON parsing took 0ms client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
Received xhr message: for(;;);[{"syncId":1,"clientId":1,"execute":[[0,null,[0,3],"return (function() { this.$server['}p']($0, true, $1)}).apply($2)"]],"timings":[50,0]}] client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
Handling message from server client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:1036:622
Handling dependencies client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:979:50
handleUIDLMessage: 0 ms client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
 Processing time was 0ms client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:200:20
Sending heartbeat request... client-21DB9CBC0117FF57F0BF06C650799FCB.cache.js:818:42
Scheduling heartbeat in 300 seconds```

Here is the application that I used to test https://github.com/aetasoul/Kekwel_Fullcalendar_Test

This is the result
image

As you can see the Dev console contains the printed messages correctly.
Can you share your project too? So I can clone it and run for test

Here's mine : https://github.com/Kekwel/FullCalendar_Test

I'll try and clone yours

EDIT:
I cloned and launch your repo, and same thing :
image

I have tested with firefox and is not browser related, for me is working.
Your project is also working for me.

I see that in your pom you have <java.version>11</java.version> but I use <java.version>1.8</java.version>

Maybe is related to this, I'll try with the 11

Yes! Found it, I can confirm that the problem is present when run the application with jdk-11.0.17_windows-x64

I did't see the problem before because all of my project are realized with jdk-8u201-windows-x64

I'll try to debug it and fix the problem

I totally forgot to tell what java version I was ! This could saved some time 😅

I totally forgot to tell what java version I was ! This could saved some time 😅

No problem, i'm installing all the stuff to debug it

We wrap the eventContent method with our own method, that adds some helper methods to the event, so that you are allowed to easily access the custom properties set to the FC by the server side. It seems, that this wrapper is the source of the issue here.

let options = this._createInitOptions(this.initialOptions);

// if the calendar is options to modify the event appearance, we extend the custom api here
// see _initCalendar for details

... other stuff

if (options.eventContent) {
    let initEventContent = options.eventContent;
    options['eventContent'] = (info) => {
        let event = info.event;
        this._addCustomAPI(event);

        if (initEventContent) {
            initEventContent.call(this._calendar, info);
        }
    };
}

this._calendar = new Calendar(this.$.calendar, options);

The issue is now, that the wrapper is simply missing a "return" before the initEventcontent.call(). Adding that return makes it working again (I tested it with Java 17 but I assume it will work with 11).

Idk why it works with Java 8 and not with Java 11.

Additional note: it still seems to not fix the "server side setting" issue. I tested it with creating a custom client side class.

Ok, seems like I have a fix so far. The only "breaking change" with this fix will be, that setting the entry content is only working before the client side element has been attached. But officially that should already be the case due to limitations of the FC. I'll play around a bit with the fix to see different constellations and then push it to the directory.

Side note: The method setEntryContentCallback will be deprecated with this fix. It is recommended to use the initial options instead, ideally by using the new method withEntryContent(String) provided by the FullCalendarBuilder. Alternatively you may set the parameter "eventContent" yourself at the initial options json object. This is, what the setEntryContentCallback method will do in future.

e.g.

FullCalendar calendar = FullCalendarBuilder.create()
        // ... other settings
        .withEntryContent("""
                function(arg) {
                    let italicEl = document.createElement('i');
                    italicEl.textContent = arg.event.title;
                    return {domNodes: [italicEl]};
                }""")
        .build();

Released with 4.1.3.

Thanks for your time ! I tested it and it's 👌