0

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)
0xcaff
  • 13,085
  • 5
  • 47
  • 55
markovuksanovic
  • 15,676
  • 13
  • 46
  • 57
  • Can you reproduce this in a small example without Angular? If so, then it might be a bug in dart:js and I can take a look. – Justin Fagnani Feb 14 '14 at 03:57
  • @JustinFagnani I can try to do that. When a few days ago I was debugging this, I came to the point where I think it's actually chromium & chrome bug. I need to write a smaller snippet though to demonstrate. – markovuksanovic Feb 14 '14 at 08:18

1 Answers1

2

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']);
}
0xcaff
  • 13,085
  • 5
  • 47
  • 55