I want to be able to call a method declared in my StartView class from the onclick event in Javascript. I am following the official GWT documentation, but am still getting a JavaScriptException TypeError - doThing is not a function error in the console. I have reviewed other similar questions here on SO and have not found a solution as of yet. I have attempted to implement a solution in JSNI and JSInterop - and what I have below is the furthest I have gotten past GWT compilation errors.
StartView.java - I call StartView.loadJS() when StartView is initialized
public void doThing() {
System.out.println("do thing");
}
public static native void loadJS() /*-{
var that = this;
$wnd.doThing = $entry(function() {
[email protected]::doThing()();
});
}-*/;
start.js (External js file, Injected into StartView via ScriptInjector. Other methods use JSInterop)
...
// Inside of my onclick handler
window.doThing();
When I click the element, I get the following error in the console:
Exception: com.google.gwt.core.client.JavaScriptException: (TypeError) : that_0_g$.doThing_0_g$ is not a function
When I put window.doThing in the console, it does return the function - so it does appear to be loading the connector, but is having trouble finding the actual method to call. Curious what else I am missing. Would appreciate any advice.
First, obligatory "Don't use JSNI for new code" - unless you project relies on an ancient GWT build, this is easier in JsInterop. First, define (or reuse) a
@JsFunctioninterface that describes the contract for JS to call into Java, make a global field that you can assign this to, and then export your instance method in vanilla java:Note that the translation of loadJS makes it clear why your JSNI isn't working (more on that in a moment) - Java will complain if you try to use
this, sinceloadJS()is static and has nothis! But, you're callingloadJS()from inside the constructor, you could pass the instance as an argument, or makeloadJS()non-static.From your question
As this is a
staticmethod, there is nothis(okay, in JS there is athis, but it isn't theStartView, it is something else entirely). SincedoThingis a non-staticmethod, there is no clear way to say whichStartViewinstance you want to havedoThing()called on.The simplest answer then is to remove
staticfrom that method, so thatthisis correctly captured, as you intended. Another choice could be to pass in aStartViewinstance toloadJSand call doThing on that instance.The error you're getting is almost certainly that
thisturns out to bewindow, and the@package.StartView::doThing()reference represents some obfuscated method name that doesn't exist on window, which makes sense, since you intendedthisto be aStartViewinstance.