Reputation: 15180
I'm trying to move most of my native JavaScript code out of JSNI methods and into scripts, and just leveraging the native JSNI methods to call those external methods.
Right now I'm having difficulties with one of my click handlers. When the user clicks a particular element, a JSNI method does some JQuery-based animation, and then calls a Java method in the callback. A simple example is this:
public native void attachClickHandler(SomeCustomPanel customPanel) /*-{
$wnd.jQuery("#theElement").click(function() {
// some JQuery animation logic here...
$wnd.jQuery("#theElement").animate({ top: "500px" }, 500, function() {
[email protected]::doSomething()();
});
// some other code here...
});
}-*/;
This code works. It compiles and works as expected. I want to move this into an external JavaScript. I tried the following. I put this in the external JavaScript:
function attachClickAction(customPanel) {
$("#theElement").click(function() {
// other stuff...
$("#theElement").animate({ top: "500px" }, 500, function() {
[email protected]::doSomething()();
});
// other stuff...
});
}
And modified the native function like this:
public native void attachClickHandler(SomeCustomPanel customPanel) /*-{
$wnd.attachClickAction(customPanel);
}-*/;
But is incorrect. The JavaScript file won't even load because this is not correct JavaScript. (Chome's dev tools give me the error message "Uncaught SyntaxError: Unexpected identifier".)
Is there a way to call a Java method from an external JavaScript file, not from a JSNI method?
I'm in GWT 2.4, if it matters.
Upvotes: 3
Views: 2640
Reputation: 37778
Yes, you can export your Java (GWT) methods as JavaScript functions, and you can put your Java objects into JavaScript variables. Here's a simple example:
@Override
public void onModuleLoad() {
exportJavaMethodsToJs();
final SomeCustomPanel firstCustomPanel = new SomeCustomPanel("first");
exportJavaObjectToJs("firstCustomPanel", firstCustomPanel);
final SomeCustomPanel anotherCustomPanel = new SomeCustomPanel("another");
exportJavaObjectToJs("anotherCustomPanel", anotherCustomPanel);
}
native void exportJavaMethodsToJs() /*-{
$wnd.doSomething = function(panel) {
[email protected]::doSomething()();
}
// Export any methods you need in JavaScript here...
}-*/;
native void exportJavaObjectToJs(final String key, final Object object) /*-{
$wnd[key] = object;
}-*/;
Then, in JavaScript (after onModuleLoad() has been called!), you can use it easily like
doSomething(firstCustomPanel);
doSomething(anotherCustomPanel);
Your example would now look like this:
jQuery("#theElement").click(function() {
// some JQuery animation logic here...
$wnd.jQuery("#theElement").animate({ top: "500px" }, 500, function() {
doSomething(firstCustomPanel);
});
// some other code here...
});
Upvotes: 2
Reputation: 6878
Although you cannot make calls to Java classe's methods directly from JavaScript with vanilla GWT, gwt-exporter does a lot of the plumbing required for calling the methods of 'Java' objects from native JavaScript.
You can do things like:
Java:
@ExportPackage("")
@Export("MYOBJ");
class MyClass implements Exportable {
public void doSomething();
}
JavaScript:
MYOBJ.doSomething();
gwt-exporter works well with GWT 2.4,
Upvotes: 4
Reputation: 15180
The answer is no, you cannot call Java methods explicitly from the external JavaScript function.
However, you can be clever and take advantage of the fact that JavaScript allows you to pass functions themselves as parameters.
I modified my JavaScript function like so:
function attachClickAction(callbackFunction) {
$("#theElement").click(function() {
// other stuff...
$("#theElement").animate({ top: "500px" }, 500, callbackFunction);
// other stuff...
});
}
And in my Java code I explicitly passed the Java method as a callback function parameter:
public native void attachClickHandler(SomeCustomPanel customPanel) /*-{
$wnd.attachClickAction(function() {
[email protected]::doSomething()();
});
}-*/;
This way, when the JSNI method compiles, it correctly calls the doSomething()
Java method, and that method call is correctly passed in its entirety to the external JavaScript function.
Upvotes: 5