Monday, December 2, 2013

Converting Polymer Elements to Dart


GitHub reports that Patterns in Polymer is 59% JavaScript and 17% Dart. I am trying hard not to favor Dart too obviously and Dart dependencies do not make nearly the mess that their JavaScript counterparts do. Still, I need to keep up with the Dart version of the book, so tonight, I am going to get my change-history Polymer element re-written in Polymer.dart. If I am still feeling ambitious, I will swap out the <polymer-localstorage> element for <polymer-ajax>

Happily, this is Dart, so getting started is far easier. I create a pubspec.yaml file with my dependencies (Polymer and Polymer Elements):
name: change_history
dependencies:
  polymer: any
  polymer_elements:
    git: https://github.com/ErikGrimes/polymer_elements
dev_dependencies:
  unittest: any
The git dependency is necessary because the most recent version published to Pub depends on a pre Dart 1.0 SDK. Hopefully the Git repository is not too bleeding edge (polymer-localstorage and polymer-ajax were both listed as ported in the versions on Pub).

After a quick pub get, I am ready to go.

My first stop is web/index.html. I copy the JavaScript version directly and make the following Dart changes in the <head> of the document:
    <!-- Load component(s) -->
    <link rel="import" href="/packages/change_history/change-sink.html">
    <link rel="import" href="/packages/change_history/store-changes.html">
    <link rel="import" href="/packages/polymer_elements/polymer_localstorage/polymer_localstorage.html">

    <script type="application/dart">export 'package:polymer/init.dart';</script>
    <script src="packages/browser/dart.js"></script>
The underscore and extra patch in polymer_localstorage/polymer_localstorage.html were unexpected. That aside, everything goes smoothly… until I try to re-implement the enteredView() handling from JavaScript. For instance, if I define the <change-sink> element as:
<polymer-element name="change-sink" attributes="was current child">
  <script type="application/dart" src="change_sink.dart"></script>
</polymer-element>
And add a corresponding change_sink.dart as:
import 'package:polymer/polymer.dart';
import 'dart:html';

@CustomTag('change-sink')
class ChangeSinkElement extends PolymerElement {
  @observable String was ='';
  @observable String current = '';
  @observable Element child = null;
  ChangeSinkElement.created(): super.created() {
    style.backgroundColor = 'red';
    print('created');
    print(children.length);
  }
  ChangeSinkElement.enteredView() : super.enteredViw() {
    style.backgroundColor = 'green';
    print("enteredView!");
  }
}
Then I see the style change from the create() lifecycle event, but not the same change from the enteredView(). Instead of green, the background color remains red:



It takes me far too long to realize that I have simply cargo coded enteredView() here. I am defining a named constructor ChangeSinkElement.enteredView() instead of a enteredView() method. It really bother me that I can make obvious mistakes like that. Happily, once found, the fix is easy enough—convert it to a method:
  // ...
  enteredView() {
    super.enteredView();
    child = children[0];

    child.
      onKeyUp.
      listen(change);
  }
  // ...
Once I make it through silly things like that, the rest of the conversions goes smoothly. Unfortunately, messing around with <polymer-ajax> will have to wait until tomorrow.


Day #953

No comments:

Post a Comment