Easy Dart <-> JS interop without dart:js

Sometimes you'll have to interact with Javascript when you are building Dart web apps. This could be because your favorite library has no Dart port yet, or you are migrating your Javascript web app to Dart.

Either way you'll end up dealing with a library called "dart:js". While dart:js is very powerful, it can also get complicated very quickly, which is why I never use it.

Instead, I use custom JavaScript events to get my Dart apps talking to Javascript and vice versa.

Since Dart is compiled to JavaScript, the code runs in the same context of execution, and because of that you can pass events to each other.

What are CustomEvents

CustomEvents API in Javascript (and Dart) is a way to send custom descriptive events to parts of your app. You know how onClick is called when a button is clicked on? Well technically you can build a UI element and when someone clicks on it, you can fire off a CustomEvent that says something like OnUIClick.

Custom Events are supported in all the browsers, http://caniuse.com/#search=CustomEvent, so using them is no problem.

Because of their flexibility, you can use them to describe all sorts of stuff happening in your code.

Imagine you wanted to initialize GoogleMaps from your Dart code. Instead of using dart:js to get an instance of the GoogleMaps object, calling some method on it which ends up being very cumbersome, like below.

var googleMap = new JsObject(context['google']['maps']['Map'], [...]);

var p1 = new JsObject(context['Point'], [5, 1]);
var p2 = new JsObject(context['Point'], [1, -2]);
print(p1.callMethod('distanceFrom', [p2])); // Prints 5.

 Example from https://www.dartlang.org/articles/js-dart-interop/

Instead we can just fire off a custom event called "initGoogleMaps" from Dart and write some event handler code in your JavaScript to initialize GoogleMaps whenever "initGoogleMaps" is received. Voila!

Example Javascript to Dart

Let's look at an example of how you use Custom Events in Javascript.

var customEvent = new CustomEvent("fromJavascriptToDart", {
    detail: {
        galleryID: "001001"
    }
});


document.dispatchEvent(customEvent);

We create a custom event called fromJavascriptToDart and dispatch it on the document. You can really dispatch it on any element, but I used document for the sake of the example.

Catching this in Dart is fairly simple, just setup a listener to your document (or whatever element you want to catch the event on) and parse it out.

document.on["fromJavascriptToDart"].listen((CustomEvent event) {
  print(event.detail.galleryID);
});

Really, it's as simple as that.

What about if we want to send an event to JavaScript land from Dart?

Example: Dart to Javascript

var payload = {"galleryId":123};
var c = new CustomEvent("fromDartToJavascript", detail: JSON.encode(payload));
    document.dispatchEvent(c);

And then in Javascript land just listen to it!

 document.addEventListener("fromDartToJavascript", function(event){
        console.log(event.detail.galleryId);
    })

Using this architecture, you can build a robust event bus that you can pass arguments and execute them on javascript functions and vice versa.

No more JsObject and long cumbersome code just to call a method in Javascript.

Just use Custom Events!