markovuksanovic
markovuksanovic

Reputation: 15906

dartlang interop js and d3 integration not working in dart

I'm trying to get a simple d3.js snippet working in AngularDart. I have a simple component:

@NgComponent(...)
class LineChart {
  Element element;
  List<num> _items;
  var d3;

  @NgOneWayOneTime('data')
  set results ( List<num> results ) {
    _items = results;
    _drawLineChart(_items);
  }

  LineChart(this.element) {
    d3 = context['d3'];
    var temp = d3.callMethod('selectAll', [new JsObject.jsify([element])]);
    var temp1 = temp.callMethod('append', ['div']);
    temp1.callMethod('html', ['Hello Me']);
  }
}

I get the following error where temp1 variable should be created. Not sure what I'm doing wrong. I used this tutorial as a reference.

NotFoundError: An attempt was made to reference a Node in a context where it does not exist.

STACKTRACE:
#0      JsObject._callMethod (dart:js:235)
#1      JsObject.callMethod (dart:js:225)
#2      JsObject.callMethod (dart:js:228)

Upvotes: 0

Views: 889

Answers (1)

0xcaff
0xcaff

Reputation: 13681

According to the Dart API reference for JsObject.jsify():

Recursively converts a JSON-like collection of Dart objects to a collection of JavaScript objects and returns a JsObject proxy to it.

object must be a Map or Iterable, the contents of which are also converted. Maps and Iterables are copied to a new JavaScript object. Primitives and other transferrable values are directly converted to their JavaScript type, and all other objects are proxied.

When you call:

var temp = d3.callMethod('selectAll', [new JsObject.jsify([element])]);

you don't need to .jsify the element because, according to the API reference for dart:js:

Proxying and automatic conversion When setting properties on a JsObject or passing arguments to a Javascript method or function, Dart objects are automatically converted or proxied to JavaScript objects. When accessing JavaScript properties, or when a Dart closure is invoked from JavaScript, the JavaScript objects are also converted to Dart.

Functions and closures are proxied in such a way that they are callable. A Dart closure assigned to a JavaScript property is proxied by a function in JavaScript. A JavaScript function accessed from Dart is proxied by a JsFunction, which has a apply method to invoke it.

The following types are transferred directly and not proxied:

  • "Basic" types: null, bool, num, String, DateTime
  • Blob
  • Event
  • HtmlCollection
  • ImageData
  • KeyRange
  • Node
  • NodeList
  • TypedData, including its subclasses like Int32List, but not ByteBuffer
  • Window

The Element inherits from Node and is automatically converted. So you simply need to call:

var temp = d3.callMethod('selectAll', [element]);

also you don't need to create temporary variables because dart has shortcuts! You can do this:

LineChart(this.element) {
  d3 = context['d3'];
  d3.callMethod('selectAll', [element])
    .callMethod('append', ['div'])
    .callMethod('html', ['Hello Me']);
}

Upvotes: 2

Related Questions