Dart Js Wrapping
This package allows developers to define well-typed interfaces for JavaScript objects. Typed JavaScript Interfaces are classes that describes a JavaScript object and have a well-defined Dart API, complete with type annotations, constructors, even optional and named parameters.
Writing Js wrapper
Here's a quick example to show the package in action.
Given a JS class like :
LatLng = function(lat, lng) {
  this.lat = lat;
  this.lng = lng;
}
LatLng.prototype.equals = function(other) {
  return this.lat === other.lat && this.lng === other.lng;
}
You can create a wrapper like :
@JsName()
abstract class LatLng {
  factory LatLng(num lat, num lng, [bool noWrap]) => $js;
  bool equals(LatLng other);
  num get lat => _lat();
  @JsName('lat')
  num _lat();
  num get lng => _lng();
  @JsName('lng')
  num _lng();
  String toString();
  String toUrlValue([num precision]);
}
Once the generator executed you will be able to use a LatLng that wraps a js LatLng.
Configuration and Initialization
Adding the dependency
Add the following to your pubspec.yaml:
dependencies:
  js_wrapping: ^0.6.0
dev_dependencies:
  js_wrapping_generator: ^0.6.0
Running the generator
See the Running generators section of the source_gen package.
Usage
Warning: The API is still changing rapidly. Not for the faint of heart
Defining Typed JavaScript Interfaces
To create a Typed JavaScript Interface you will start by creating a class marked with @JsName(). It will be the template used to create a js interface.
@JS('google.maps')
library google_maps.sample.simple;
import 'package:js_wrapping/js_wrapping.dart';
@JsName()
abstract class LatLng {
  factory LatLng(num lat, num lng, [bool noWrap]) => $js;
  bool equals(LatLng other);
  num get lat => _lat();
  @JsName('lat')
  num _lat();
  num get lng => _lng();
  @JsName('lng')
  num _lng();
  String toString();
  String toUrlValue([num precision]);
}
The generator will provide a new library mylib.g.dart containing :
// GENERATED CODE - DO NOT MODIFY BY HAND
// **************************************************************************
// JsWrappingGenerator
// **************************************************************************
// Copyright (c) 2015, Alexandre Ardhuin. All rights reserved. Use of this
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
@JS('google.maps')
library google_maps.sample.simple;
import 'package:js_wrapping/js_wrapping.dart';
@JS()
class LatLng {
  external LatLng(num lat, num lng, [bool noWrap]);
  external bool equals(LatLng other);
  external String toString();
  external String toUrlValue([num precision]);
}
extension LatLng$Ext on LatLng {
  num get lat => _lat();
  num get lng => _lng();
  num _lat() => callMethod(this, 'lat', []);
  num _lng() => callMethod(this, 'lng', []);
}
Constructors to create js object
If LatLng is a js object/function you can create a new instance in js with
LatLng(). To make it possible to create such js instance from the Dart-side
you have to define a factory constructor:
@JsName()
abstract class LatLng {
  factory LatLng(num lat, num lng, [bool noWrap]) => $js;
}
This will provide:
@JS()
class LatLng {
  external LatLng(num lat, num lng, [bool noWrap]);
}
It's now possible to instantiate js object from Dart with LatLng().
Properties and accessors
Properties or abstract getters/setters can be added to the class and will generate getters and setters to access to the properties of the underlying js object.
@JsName()
abstract class Person {
  factory Person() => $js;
  String firstname, lastname;
  int get age;
  void set email(String email);
}
This will provide:
@JS()
class Person {
  external Person();
  external String get firstname;
  external set firstname(String value);
  external String get lastname;
  external set lastname(String value);
  external int get age;
  external void set email(String email);
}
Methods
The abstract methods will be implemented the same way :
@JsName()
abstract class Person {
  factory Person() => $js;
  String sayHelloTo(String other);
  void fall();
}
This will provide:
@JS()
class Person {
  external Person();
  external String sayHelloTo(String other);
  external void fall();
}
Names used
constructors
You can override this name by providing a  JsName('MyClassName') on the class.
@JsName('People')
abstract class Person {
  factory Person() => $js;
  String sayHelloTo(Person other);
  Person get father;
}
members
You can override this name by providing a JsName('myMemberName') on the member.
@JsName()
abstract class Person {
  @JsName('daddy') Person get father;
}
Tips & Tricks
anonymous objects
It's common to instantiate anonymous Js object. If your private classe maps an
anonymous object you can add @anonymous on it.
@JsName()
@anonymous
abstract class Foo {
  factory Foo() => $js;
}
This generates:
@JS()
@anonymous
class Foo {
  external factory Foo();
}
create getter from method
If a js object as a getXxx() function you would like to map on the dart side
with a get xxx you can do something like that:
abstract class Person {
  String get firstname => _getFirstname();
  String _getFirstname();
}
@JsName()
abstract class Person {
  factory Person() => $js;
  String get firstname => _getFirstname();
  @JsName('getFirstname')
  String _getFirstname();
}
This can be applied to any redirection you'd like to do.
Libraries
- js_wrapping
 - The js library allows Dart library authors to define Dart interfaces for JavaScript objects.