vaadin-fullcalendar icon indicating copy to clipboard operation
vaadin-fullcalendar copied to clipboard

Wiki example of Customize the entry content

Open Kekwel opened this issue 2 years ago • 7 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 ?

Kekwel avatar Oct 25 '22 07:10 Kekwel

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?

aetasoul avatar Oct 25 '22 11:10 aetasoul

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 ?

Kekwel avatar Oct 25 '22 13:10 Kekwel

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

aetasoul avatar Oct 25 '22 14:10 aetasoul

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 !

Kekwel avatar Oct 25 '22 14:10 Kekwel

I'll check it as soon as possible

aetasoul avatar Oct 25 '22 14:10 aetasoul

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)

aetasoul avatar Oct 31 '22 21:10 aetasoul

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.

aetasoul avatar Oct 31 '22 21:10 aetasoul

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

Kekwel avatar Nov 02 '22 08:11 Kekwel

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```

Kekwel avatar Nov 02 '22 09:11 Kekwel

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

aetasoul avatar Nov 03 '22 11:11 aetasoul

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

Kekwel avatar Nov 03 '22 12:11 Kekwel

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

aetasoul avatar Nov 03 '22 13:11 aetasoul

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

aetasoul avatar Nov 03 '22 13:11 aetasoul

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

Kekwel avatar Nov 03 '22 14:11 Kekwel

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

aetasoul avatar Nov 03 '22 14:11 aetasoul

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.

stefanuebe avatar Nov 14 '22 07:11 stefanuebe

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

stefanuebe avatar Nov 14 '22 07:11 stefanuebe

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.

stefanuebe avatar Nov 14 '22 08:11 stefanuebe

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();

stefanuebe avatar Nov 14 '22 08:11 stefanuebe

Released with 4.1.3.

stefanuebe avatar Nov 14 '22 09:11 stefanuebe

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

Kekwel avatar Nov 16 '22 15:11 Kekwel