Search code examples
dartdart-js-interop

js package - interface to object


Using https://pub.dartlang.org/packages/js to interface a js class in this manner, works fine:

@JS()
class ObjJS {
  external ObjJS();
  external String fullName();
}

Now I want to expose the method in an other class, so fare I only have solved this with duplication of the method. This works, but will grow, when more methods are added. Needed is some kind of mixin or inheritance, but not accepted for this interop class. jselem is the library name

class ObjDart {
  jselem.ObjJS _objJS = new jselem.ObjJS();

  String fullName(){
    return _objJS.fullName();
  }
}

Are there more elegant ways to solve this?


Update for better illustration

Things works, the question regards if there was better ways to expose the methods/properties of the interfaced Javascript class. The example above is just minimal, so not that illustrative. To get better illustration, take the ChartDataSet from here : https://github.com/google/chartjs.dart/blob/master/lib/chartjs.dart Just for illustration, let say with this, on the Dart side is created a Dart class StreamChartDataSet, which adds functionality for reading online data from an url. Since StreamChartDataSet can't inherit or mixin from ChartDataSet the solution above gives:

class StreamChartDataSet {
   ChartDataSet _chartDataSet;
   ...
   String get label => _chartDataSet.label;
   set label(fial String v) => _chartDataSet.label(v);
    ...
}

This are many methods and pure mechanical work. When finished with this, just to hope that ChartSettings goes unmodified :-) I am working with other things, but using Charjs.dart for illustration.


Solution

  • To clarify, you want to be able to extend a @JS() annotated class, is that correct? I don't think works since the @JS() class doesn't really exist until compile-time.

    A couple options:

    1. Someone could develop a code generator that looks at a @JS()-annotated class, and remove the boilerplate by doing basically what you're doing for you. Not super elegant, but at least helps.

    2. You could file a bug against package:js to support extending.

    In my opinion though, I'm a huge supporter of composition over extension, especially over classes you don't directly control. For example, if the JS-API changes from fullName to firstName and lastName, you can maintain the same API by just changing your getter:

    String fullName() => _js.firstName + _js.lastName;
    

    It's up to you though.