Search code examples
dartdart-polymerdart-pub

model class imported from packaged library?


What is the correct way to use a model in polymer element when model class is defined in imported packaged library?

I believe I did it correct (based on more articles e.g. How to subscribe to change of an observable field).

It works in DARTIUM but when it's built to JS it doesn't. I can't really figure out what's happening there, see logs down. Listeners and value in field behave strange.

Key factors: my model class is packaged in shared library for some reasons and have to use my input element

What am I missing? Or is there a bug in dart2js?


FILES and LOGS

testlib.dart (just a model in packaged library, not a part of polymer app):

library testlib;
import 'package:observe/observe.dart';

class MyModel extends Object with Observable{
  @observable String foo;
  String toString(){
    return "MyModel[foo:$foo]";
  }
}

And in polymer app we have:

all_elements.dart (model is imported using package:...)

library test;
import 'package:polymer/polymer.dart';
import 'package:testlib/testlib.dart'; //!!!! note this is important, I need shared model

@CustomTag('my-input')
class MyInput extends PolymerElement {
  @published String value;
  valueChanged(oldValue){
    print('text changed from "$oldValue" to "$value"');
  }
  MyInput.created() : super.created();
}

@CustomTag('my-form')
class MyForm extends PolymerElement {
  @observable MyModel model = new MyModel();
 modelChanged(oldValue){
    print('text changed from "$oldValue" to "$model"');
  }

  MyForm.created() : super.created();
  void ready(){
    model.changes.listen((changes){
      print('model properties changed $changes');
    });
  }
}

and all_elements.html

<polymer-element name="my-input">
  <template>
    <p>My Input</p>
    <input type="text" value="{{value}}"/>
  </template>
</polymer-element>

<polymer-element name="my-form">
  <template>
    <my-input value="{{model.foo}}"></my-input>
  </template>
</polymer-element>

<script type="application/dart" src="all_elements.dart"></script>

and app entry point: testapp.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test app</title>
    <link rel="import" href="all_elements.html">
    <script type="application/dart">export 'package:polymer/init.dart';</script>
    <script src="packages/browser/dart.js"></script>
  </head>
  <body>
    <my-form></my-form>
  </body>
</html>

LOGS:

Everything works fine till it's built to JS. When trying to write word "hello" to input I get:

DARTIUM - OK

text changed from "null" to "h"
model properties changed [#<PropertyChangeRecord Symbol("foo") from: null to: h>]
text changed from "h" to "he"
model properties changed [#<PropertyChangeRecord Symbol("foo") from: h to: he>]
text changed from "he" to "hel"
model properties changed [#<PropertyChangeRecord Symbol("foo") from: he to: hel>]
text changed from "hel" to "hell"
model properties changed [#<PropertyChangeRecord Symbol("foo") from: hel to: hell>]
text changed from "hell" to "hello"
model properties changed [#<PropertyChangeRecord Symbol("foo") from: hell to: hello>]

JavaScript - PROBLEM (type "hello" - get "hel", type "mystery" - get "mytr" )

text changed from "null" to "h" 
model properties changed [#<PropertyChangeRecord Symbol("foo") from: null to: h>] 
text changed from "h" to "he" 
text changed from "he" to "h" 
model properties changed [#<PropertyChangeRecord Symbol("foo") from: h to: he>] 
text changed from "h" to "hl" 
text changed from "hl" to "he" 
model properties changed [#<PropertyChangeRecord Symbol("foo") from: he to: hl>]
text changed from "he" to "hel" 
text changed from "hel" to "hl" 
model properties changed [#<PropertyChangeRecord Symbol("foo") from: hl to: hel>] 
text changed from "hl" to "hlo" 
text changed from "hlo" to "hel"

Solution

  • The js generated by pub build is quite different when there is a polymer transformer in the dependent package vs. not, particularly the js code that is involved in detecting and propagating observable changes.

    Try adding a polymer transformer to the import package pubspec:

    name: testlib dependencies: browser: any observe: any polymer: any transformers: - polymer: entry_points:

    (Note that no actual entry_points value is required, just the presence of the polymer transformer entry.)