How to expose JS patch function of Incremental DOM library in GWT app using @JsInterop

221 views Asked by At

I would like to use Incremental DOM library in my GWT app.

https://google.github.io/incremental-dom/#about

As I am coming from the Java world, I struggle with concepts of JavaScript namespaces and modules. I was able to use Closure Compiler with closure version of Incremental DOM (has to be build from sources).

It starts with the following line:

goog.module('incrementaldom');

So if I was to use it in regular JS I would type:

var patch = goog.require('incrementaldom').patch;

And then the patch function would be available in the scope of my code. But how to make it accessible from @JsInterop annotated classes?

I tried something like:

public class IncrementalDom {

  @JsMethod(namespace = "incrementaldom", name = "patch")
  public static native void patch(Element element, Patcher patcher);

  @JsFunction
  @FunctionalInterface
  public interface Patcher {
    void apply();
  }

}

But it doesn't work. I get this error in the runtime:

(TypeError) : Cannot read property 'patch' of undefined

So I guess I have to somehow expose the incrementaldom module or at least only the patch method. But I don't know how.

1

There are 1 answers

0
morisil On BEST ANSWER

After fighting for the whole day I found the solution. In the goog.module: an ES6 module like alternative to goog.provide document I found the missing information about the role of goog.scope function - required modules are visible only within the scoped call.

I created another Closure JS file named incrementaldom.js:

goog.provide('app.incrementaldom'); // assures creation of namespace
goog.require("incrementaldom");

goog.scope(function() {
  var module = goog.module.get("incrementaldom");
  var ns = app.incrementaldom;
  app.incrementaldom.patch = module.patch;
});

goog.exportSymbol("app.incrementaldom", app.incrementaldom);

And now I can call it from Java code like this:

public class IncrementalDom {

  @JsMethod(namespace = "app.incrementaldom", name = "patch")
  public static native void patch(Element element, Patcher patcher);

  @JsFunction
  @FunctionalInterface
  public interface Patcher {
    void apply();
  }

}

Still I have to define every object exported in original module separately in the Closure JS file. Fortunately I only need patch method. I hope one day I will find less cumbersome way for @JsInterop with goog.module :(