Thursday, September 26, 2013

Quick-Patching a Dart Package (Polymer.dart)


Thanks to the (early) power of Polymer.dart, I was able to create a custom tag for the ICE Code Editor:
<ice-code-editor src="embed_a.html" lineNumber="49"></ice-code-editor>
Which created an embedded version of the browser in a web page, with content loaded from embed_a.html and scrolled so that the very important line number 49 is at the top of the mini editor window:



I was especially excited that I was able to get the attribute reading working last night after lamenting just the night before that it was impossible with this early version of Polymer.dart. I am excited about the power of Polymer and it seems worth exploring further.

From last night's comments Charlie M indicates that I might be able to make at least two improvements. First off, the camel-cased lineNumber attribute on my custom <ice-code-editor> element is actually supposed to be line-number—it seems that Polymer will take care of converting to the camel-cased bound variable for me. Secondly, there may be some shenanigans that I can play to get attribute variable binding working without last night's hack.

I start addressing both by updating the Polymer template so that it accepts the hyphenated line-number attribute and uses the lineNumber bound variable:
<polymer-element name="ice-code-editor" attributes="src,line-number">
  <template>
    <h1>The src is "{{src}}" ({{lineNumber}})</h1>
    <content></content>
  </template>
  <script type="application/dart" src="ice_polymer.dart"></script>
</polymer-element>
Then, in the backing ice_polymer.dart code, I add some default values for my attributes:
import 'dart:html';
import 'package:polymer/polymer.dart';
import 'package:ice_code_editor/ice.dart' as ICE;

@CustomTag('ice-code-editor')
class IceCodeEditorElement extends PolymerElement with ObservableMixin {
  @observable String src = '';
  @observable int lineNumber = 0;

  void created() {
    super.created();
    // src = host.attributes['src'];
    // lineNumber = int.parse(host.attributes['line-number']);

    // Setup ICE like normal here...
  }
}
I also comment out last night's hack that bound the observed variables, src and lineNumber, to the attributes from the custom element.

Instead, I go back to where the custom element is used and try to supply attributes with expressions instead of values:
<ice-code-editor src="embed_a.html" line-number="{{49}}"></ice-code-editor>
Unfortunately, that does not work:



Try as I might, no variation of expression, regular attribute value, or initial values in the IceCodeEditorElement class seems to have any effect. With the current version of Polymer.dart, last night's hack (or something similar) would appear to be the only way to access attributes.

At least currently. There are two ongoing code discussions that look to be trying to solve the problem. The older of the two looks to have been a first pass at the problem. The second review seems to be nearing a consensus as to the actual approach.

I am going to give the first approach a whirl tonight. It touches on only a single file in a single package whereas the second touches on multiple files in three packages. Since I am using Dart, modifying a single dependency is a breeze. I copy the Dart Pub package from my local cache into my repos directory, download the patch, and apply it:
➜  repos  cp -r ~/.pub-cache/hosted/pub.dartlang.org/polymer-0.7.5 .      
➜  repos  cd polymer-0.7.5 
➜  polymer-0.7.5  wget https://chromiumcodereview.appspot.com/download/issue22417004_1.diff
➜  polymer-0.7.5  patch -p1 < issue22417004_1.diff
patching file lib/polymer_element.dart
Hunk #1 succeeded at 120 (offset 3 lines).
Back in my ICE project, I update the project's pubspec.yaml to depend on my modified, local version of Polymer:
name: ice_code_editor
# ...
dependencies:
  # ...
  polymer:
    path: /home/chris/repos/polymer-0.7.5
After a quick pub update and a restart of pub serve, I find that the patch did the trick:

With this particular patch, the custom tag's attributes do not need to be expressions—regular values work just fine:

<ice-code-editor src="embed_a.html" line-number="49"></ice-code-editor>
I do see why this patch was just the starting point for discussion. I find that it does not work if I fail to supply an initial value for the line number bound variable:
class IceCodeEditorElement extends PolymerElement with ObservableMixin {
  @observable String src = '';
  @observable int lineNumber;
  // ...
}
That was fun. The ability to quick-patch a single package like that is a killer feature for Dart. I am glad to have a grip on where things stand on getting bound attributes working in Polymer.dart. I could probably leave it at this, but I may give the three-package patch a whirl tomorrow. Just for the fun of it.

Day #886

No comments:

Post a Comment