bryntum gantt webcomponent integration ✅

Hi,
I want to use the Gantt chart library from Bryntum https://bryntum.com/products/gantt/ in my Vaadin 23 app.
I already integrate the web component version on a fresh vaadin view with the help of @quintessential-ibex PoC from Vaadin 14 https://github.com/mstahv/bryntum-gantt-vaadin and also add an event listener for custom Gantt events I want to propagate to the server. This works properly. :white_check_mark:
On the server side, I create a fresh Vaadin component as follows:

@JsModule(value = "./gantt.wc.module.js")
@JavaScript("./ganttConnector.js")
@CssImport("./gantt.classic.css")
public class GanttChart extends Div {

The chart is visible and usable. :white_check_mark:

Now I need to receive those gantt specific events e.g. taskResizeEnd from the client.
As mentioned in the Vaadin doc I add a custom tag annotaion

@Tag("bryntum-gantt")

to the java component class. After insert those line, the whole chart component disappear from the UI. The DOM inspector still shows the element with the custom tag <bryntum-gantt> but no elements on screen ?

Also the event class I introduce at server side doesn’t receive any event.

@DomEvent("taskResizeEnd")
public class GanttEvent extends ComponentEvent<GanttChart> {

How those custom events from the JS Gantt component is propagated to the client ?
Simple component element events e.g. ‘click’ properly send to the server, as this works:

ganttChart.getElement().addEventListener("click", event -> {
    System.out.println("click: " + event);
});

But this doesn’t work for custom events e.g. taskResizeEnd and the element click event doesn’t contain the needed data.

So there are two questions:

  1. Is the @Tag annoation mandatory for the client-server-communication and I have to inspect, why after adding this, the web component becomes invisible ?
  2. What is needed to send web component specific events to the client ? The client side is setup properly but how to propagate such an event to the server?

Thanks in advance
Dominik

Hi! Do you have your branch somewhere available?

I have tried to explain use of custom events from client to server with custom components here Create a custom component with Lit | Vaadin

See in that blog post how custom event tab-changed is fired in the web component and observed in Java API part using @DomEvent annotation.

Hi Matti, I’ve forked your repo and include my modification here https://github.com/dominik42/bryntum-gantt-vaadin
It would be nice, if you can take a look.

Thank you @yummy-rhino for your response. Some open questions after reading your blog post:

  1. Is it necessary to have a typeScript class extending from LitElement for an existing 3rd party webcomponent ? The Bryntum Gantt is available as gantt.wc.module.js : Modules format bundle with WebComponents so I assume it’s enough to include that one simply with @JsModule(value = "./gantt.wc.module.js") ?

  2. It seems, that the @Tag annotation is mandatory, so maybe this is the first stumbling block: after adding this tag, the component disappear on screen. But there is a webcomponent demo at Bryntum showing the component with a custom tag, so basically that should work: https://bryntum.com/products/gantt/examples/webcomponents/

LitElement should be used only for LitElement integrations and even there required only for custom template features.

Not even our core components extend the LitElement class, even though they use Lit on the client side.

ok, makes it easier :slightly_smiling_face: In the meantime I could solve the problem with the @Tag annotation: if I switch back from the webcomponent module to the normal module it works :man_shrugging:
Remains the problem with dispatching the event:
this.dispatchEvent(customEvent) seems a function from the LitElement class they I don’t come from. Are they any other plain vanilla JS methods to dispatch events from client to Vaadin Flow server backend ?

That’s standard JS API: Creating and triggering events - Event reference | MDN

Ah, ok, than I guess the problem is that this does refer to the context in which the on callback is called rather than the component instance. How can this be fixed ? e.g. how an arrow function instead of the explicit function can be applied here (because an arrow function should solve that problem according this SO issue https://stackoverflow.com/questions/69992323/vaadin-14-polymer-element-this-dispatchevent-is-not-a-function

This is the source:

window.Vaadin.Flow.brymtumGanttConnector = {
    initLazy: function (c, rows, deps) {
        // ...
        c.chart.on({
            taskResizeEnd(event) {
                console.log('GANTT taskResizeEnd: ', event);
                const customEvent = new CustomEvent('task-resize-end', {
                        detail: event,
                        composed: true,
                        cancelable: true,
                        bubbles: true
                 });
                 this.dispatchEvent(customEvent);
            }
        });
    }
}

ok, problem solved by using this client side event listener:

c.chart = new Gantt({
    // ...
    listeners : {
        taskResizeEnd : (event) => {
            console.log('GANTT taskResizeEnd: ', event);
            const customEvent = new CustomEvent('task-resize-end', {
                detail: event,
                composed: true,
                cancelable: true,
                bubbles: true});
            console.log('custom event:', customEvent);
            this.dispatchEvent(customEvent);
        }
    }

});

Also with this new implementation, the error this.dispatchEvent is not a function still exists

Hi @quintessential-ibex thanks for your message but the problem still occur due to this.dispatchEvent(...)is called inside the Gantt component event listener method and it seems to be that thisis in this scope something other. The Bryntum Gantt docs at https://bryntum.com/products/gantt/docs/guide/Gantt/basics/events says someting about tweaking the this object inside such event listener, but also did not work for me. Any other suggestions ?

So … finally I finished that tough issue. Just like every time, it’s the javaScript, stupid
The problem was to find any object, capable to dispatch events e.g. containing an dispatchEvent() method.
While starring into to Debugger of the Browser webdev tools, I discovered an child attribute of current scope thiscalled _adaopt. This was the Bryntum Chart Object starting with the custom tag. Therefor this._adopt.dispatchEvent(...) successfully sends the event to the backend where I received it. But this._adoptlooks not very reliable to me, so I switched to document.getElementsByTagName('bryntum-gantt').item(0).dispatchEvent(customEvent);which seems to be more stable. Of course, I have to fulfill the equality of the tag name and always use just one gantt chart per view but this is ok in my case. So … mission accomplished
Thank you guys, for your help which leads me into the right direction. :pray:t2:

bryntum gantt webcomponent integration :white_check_mark:

Awesome! JS hacker Dominik :sunglasses:

Push your changes to the the repo when you have time, would be nice to try it out and show the latest integration to the mr Bryntum himself :slightly_smiling_face: He is repeatedly asking me when the integration is ready.

I’m pleased to do…