javascriptvaadinvaadin-flowvaadin14

Vaadin flow javascript to Java call


Following this tutorial https://vaadin.com/blog/calling-java-from-javascript I'm trying to call a Java function from javascript but that doesn't seem to work as expected.

I'm having a View that contains a button which, on its onClick handler, triggers a call to a Javascript function, which works as expected.

The problem I'm having is that the getElement() that I`m passing to the javascript function is undefined when it reaches the javascript side of things.

My code looks as follows:

@JavaScript("./js/script.js")
public class RouteGraphicsView extends Div {
....
        Button b = new Button("Test Button");
        b.addClickListener(new ComponentEventListener<ClickEvent<Button>>() {

            private static final long serialVersionUID = 1L;

            @Override
            public void onComponentEvent(final ClickEvent<Button> event) {
                UI.getCurrent().getPage().executeJs("greet($0, $1)", "test name", UI.getCurrent().getElement());
            }
        });
....
}

The above call reaches the script.js file which looks like this

window.greet = function greet(name, element) {
    console.log("Hello, I am greeting you, " + name);
    
    try {
        console.log("Element ", element);
        console.log("Logging 1", element.$server);
    } catch (e) {
        console.log(e);
    }
}

The output shown by the greet function above is

Hello, I am greeting you, test name
vaadin-bundle-62ac8b…b56c6.cache.js:4813 Element  
vaadin-bundle-62ac8b…b56c6.cache.js:4813 Logging 1 undefined

Since the element.$server is undefined I can not get the javascript function to call my greet function in the View, which is annotated with @ClientCallable

@ClientCallable
public void greet(final String name) {
    System.out.println("Called from JavaScript: " + name + " \n\n\n");
}

I've tried various other ways of calling the script.js, like using button's element to invoke the executeJs function or passing the button's element (b.getElement()) as an argument to the function but to no avail.

What am I doing wrong ?


Solution

  • You're doing element.$server on the element that you passed as UI.getCurrent().getElement(). This corresponds to the UI instance and not an instance of the RouteGraphicsView class that (I assume) has the @ClientCallable method. Using the button would also not work for the same reason.

    You should pass an instance of the view, which in your case needs to be written as RouteGraphicsView.this because of the way the regular this refers to the click listener.