Mixing Elemental2 with GWT Widgets

128 views
Skip to first unread message

Craig Mitchell

unread,
Jul 30, 2025, 12:34:49 AMJul 30
to GWT Users
I've switched to use Elemental2 for a few things.  The rest of my app still uses the standard GWT widgets.

I can bind directly to the Elemental2 elements from the GWT UI Binder, however, if I programatically want to add an Elemental2 element to a GWT Widget, there doesn't seem to be a direct way to do this.

Eg: How would you add the Elemental2 HTMLCanvasElement, to a GWT SimplePanel using its setWidget method?

To work around this, I created an "Elemental2Widget":

import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Widget;
import jsinterop.base.Js;

public class Elemental2Widget<T> extends Widget {
  public Elemental2Widget(T elemental2Widget) {
    Element element = Js.cast(elemental2Widget);
    setElement(element);
  }
  public T getElemental2Widget() {
    return Js.cast(getElement());
  }
}

Now I can call it like this:

simplePanel.setWidget(new Elemental2Widget<>(htmlCanvasElement));

Is this how people mix Elemental2 with GWT widgets?  Or is there a better way?

Craig Mitchell

unread,
Jul 30, 2025, 8:36:45 PMJul 30
to GWT Users
On the off chance someone reads the above post and thinks Elemental2 isn't very good.  Just to make it clear, Elemental2 is awesome.  Just now I needed a WeakHashMap.  GWT said no.  Elemental2 said sure can, with JsWeakMap.  Love it!

Ralph Fiergolla

unread,
Jul 31, 2025, 2:20:40 AMJul 31
to google-we...@googlegroups.com
Craig! 
Don’t worry - i am following your Elemtal2 Experience closely. It is on my to-do list for quite some time now. Thanks for sharing! 
Ralph 

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/google-web-toolkit/7a9446c7-32b5-4a1a-84ba-2c7200901122n%40googlegroups.com.

Craig Mitchell

unread,
Jul 31, 2025, 5:02:25 AMJul 31
to GWT Users
Excellent!  Will be good to have some company on the Elemental2 journey.  🙂

While I'm sharing...  I wrote a method to load an HTMLImageElement from a base64 encoded string:

public static void loadImage(String imgBase64, Consumer<HTMLImageElement> loaded) {
  HTMLImageElement img = (HTMLImageElement)DomGlobal.document.createElement("img");

  img.onload = e -> {
    loaded.accept(img);
    return null;
  };

  img.onerror = e -> {
    DomGlobal.console.error("Failed to load image.");
    return null;
  };

  img.src = imgBase64;
}

What I don't understand is why onload and onerror need a return value?  I just return null as I've no clue what the return value should be.

Jens

unread,
Jul 31, 2025, 5:09:45 AMJul 31
to GWT Users
That is usually what you would do. That is how GWT itself implements widgets and it does not really matter if you use an elemental2 element or a GWT element since both link directly to the underlying js type in the browser and thus you can cross cast them.

So instead of just having an adapter widget you could also implement your own widgets using elemental2 element as a basis. Imagine you would rename your Elemental2Widget to Artboard or SceneCanvas and then you could implement all the methods you need on that widget similar to what GWT does with its own widgets.

What you cannot do is elemental2Element.append(gwtWidget.getElement()). In that case events on the GWT widget will not work because GWT widgets have their own event mechanism which requires a continuous widget parent/child relation up to the root panel (or some hackery to make it work).

-- J.

Jens

unread,
Jul 31, 2025, 5:25:56 AMJul 31
to GWT Users
What I don't understand is why onload and onerror need a return value?  I just return null as I've no clue what the return value should be.

Because these on<Event> properties and their functions are defined that way. For example in the old days you could return false in an onclick function to suppress the click default action of the browser. These days it is recommended to always use addEventListener() instead of these event properties and to suppress the default action you call event.preventDefault().

Also in JS a function basically always have some return value, e.g.

function() {
  return;
  return undefined;
  // no return statement at all
}

is all the same and returns undefined. That is why Promises in elemental2 also feel a bit clunky compared to JS. Promises allow you to return a new Promise/thenable in your success/catch callback methods so elemental2 has to define a return type for these callback functions. If you do not want to return a Promise/thenable in JS then you simply do not write a return statement but in Java you now have to write return null.

-- J. 

Craig Mitchell

unread,
Jul 31, 2025, 5:29:07 AMJul 31
to GWT Users
Excellent  explanations.  Makes sense.  Thanks Jens.

Craig Mitchell

unread,
Jul 31, 2025, 5:36:07 AMJul 31
to GWT Users
btw:  With addEventListener, we have to use hard coded strings for the event name.  Eg: 

img.addEventListener("load", e -> doStuff());

Or are there event name constants we can use somewhere?

Jens

unread,
Jul 31, 2025, 5:45:19 AMJul 31
to GWT Users
btw:  With addEventListener, we have to use hard coded strings for the event name.  Eg: 

img.addEventListener("load", e -> doStuff());

Or are there event name constants we can use somewhere?

GWT has com.google.gwt.dom.client.BrowserEvents but it is not a complete list.

-- J.

Craig Mitchell

unread,
Jul 31, 2025, 5:56:05 AMJul 31
to GWT Users
My OCD has been satisfied.  🙂  Thanks again Jens.

public static void loadImage(String imgBase64, Consumer<HTMLImageElement> loaded) {
  HTMLImageElement img = (HTMLImageElement)DomGlobal.document.createElement(ImageElement.TAG);

  img.addEventListener(BrowserEvents.LOAD, e -> loaded.accept(img));
  img.addEventListener(BrowserEvents.ERROR, e -> DomGlobal.console.error("Failed to load image."));
  img.src = imgBase64;
}

Juan Pablo Gardella

unread,
Jul 31, 2025, 6:05:41 AMJul 31
to google-we...@googlegroups.com
Thanks for sharing!

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.

Gerard Keiser

unread,
Jul 31, 2025, 9:17:54 AMJul 31
to GWT Users
Elemento has event more event types, if you need: https://hal-console.gitbook.io/elemento/event-handlers

Craig Mitchell

unread,
Jul 31, 2025, 9:20:39 PMJul 31
to GWT Users
Thanks Gerard, I'll check out Elemento.

Elemental2 is a little lacking on strongly typing events.  Eg: Adding this code:

myElement.addEventListener(BrowserEvents.MOUSEDOWN, event -> {
  MouseEvent mouseEvent = Js.cast(event);
  ...
});

I could mess up on the event name, or the typecast, and I wouldn't know until runtime.

And unless you read the JS docs, it's not obvious what event name, maps to what event object.

Having something that strongly types all the events, so it was obvious and stops you messing up, would be great.

Jens

unread,
Aug 1, 2025, 5:32:29 AMAug 1
to GWT Users
Someone here once did


which is similar to elemental2 but has a more natural Java API. For example for common event types specific methods had been added similar to GWT widgets.

But I don't know about the state and future of that library. Maybe you ask the maintainer about it. It might be an alternative for you but I am pretty sure it has other pain points, as always :)

-- J.

Reply all
Reply to author
Forward
0 new messages