1

I have created a form with Vaadin Flow (Vaadin version 21) with a save button. This form is then shown in a JavaFX WebView (Version 17.0.1) and now I want to listen to events in the form like save button from JavaFX, so I can update JavaFX parts of the application. I have seen examples like:

How to retrieve components from HTML webview in JavaFX

But they don't work since doc.getElementById("xxx") does not work at all and returns null. If I use the xpath method described there, I do get the button element, but then the adding the listener by calling the

((EventTarget) button).addEventListener("click", e -> doSomeAction(), false);

does not help. When I click the button the Vaadin listener works but the "javafx" listener does not get the event.

So my question is if there is a known solution for this Use Case?

Anna Koskinen
  • 1,362
  • 3
  • 22
Keyhan
  • 2,370
  • 2
  • 19
  • 22

1 Answers1

1

You can invoke Java methods from JavaScript with upcalls. It works by assigning a JavaScript object to a Java one:

JSObject jso = (JSObject)webEngine.executeScript("window");

jso.setMember("java", new JavaObj());

Full example:

public class JavaObj {
  public void myMethod() {
    ...
  }
}
webEngine.setJavaScriptEnabled(true); // Obviously...

webEngine.getLoadWorker().stateProperty().addListener((observable, oldState, newState) -> {
  if(newState == Worker.State.SUCCEEDED) {
    JSObject jso = (JSObject)webEngine.executeScript("window");

    jso.setMember("java", new JavaObj());
  }
});
((EventTarget) button).addEventListener("click", e -> UI.getCurrent().getPage().executeJs("java.myMethod()"), false);

More about upcalls here.

Oliver
  • 1,465
  • 4
  • 17
  • I don't see how this could change anything. I was wondering also the "window" and "java" you picked, are they just madeup thing or do they actually have to be set to those values? – Keyhan Nov 21 '21 at 19:51
  • `JSObject jso = (JSObject)webEngine.executeScript("window")` returns the JavaScript object `window` represented by a Java `JSObject`. `jso.setMember("java", new JavaObj())` adds a new object to `window`, that references back to a Java object, `new JavaObj()`. The choice of `window` is necessary, but the choice of `java` is arbitrary. – Oliver Nov 22 '21 at 20:08
  • Hi, did this answer your question? Do you need more help? – Oliver Dec 23 '21 at 16:12
  • Hi, I tried your suggestion, but it did not help. Right now I am busy with something else. – Keyhan Dec 25 '21 at 09:59
  • OK, now I got it to work as you wrote. Must be added that in the vaadin code you have also to call the myMethod as a javascript call and not a java call as you wrote here. – Keyhan Jan 25 '22 at 08:43
  • @Keyhan Glad to hear it. What do you mean call `myMethod` as a JavaScript call? Do you mean instead of `java.myMethod()`, you used `webEngine.executeScript`? – Oliver Jan 25 '22 at 15:54
  • 2
    In the vaadin code when you click the button you need to do UI.getCurrent().getPage().executeJs("java.myMetho()") – Keyhan Jan 26 '22 at 12:41
  • You're right, that is a typo. Updating my post. – Oliver Jan 26 '22 at 15:24
  • 1
    Ok, now it is done! – Keyhan Feb 18 '22 at 07:40