Thursday, October 2, 2014

Custom_element_apigen and Using JavaScript Polymer Elements in Dart


I had little luck using my apply-author-styles JavaScript Polymer element in Polymer.dart last night. Well, I had great luck if you count hand-editing Core Elements in order to get it to work. Personally, I do not count that as good luck.

What I do count as good luck is readers like James Hurford writing to tell me about potential solutions that I may have overlooked. In this case, I have not tried the custom_element_apigen Dart Pub package, which “lets you wrap custom elements written with polymer.js and provide a Dart API for them.” I do not necessarily need a Dart API, but only the ability to use <apply-author-styles>. Still, it seems worth a try.

To install the JavaScript <apply-author-styles> last night, I had introduced a project-level .bowerrc file to install it in lib/bower_components:
{
  "directory": "lib/bower_components"
}
The custom_element_apigen package would rather this go into lib/src:
{
  "directory": "lib/src"
}
I already have a bower.json that includes apply-author-styles as a dependency:
{
  "name": "bootstrap_example",
  // ...
  "dependencies": {
    "bootstrap": "~3.1.0",
    "apply-author-styles": "eee-c/apply-author-styles"
  }
}
So I remove last night's install (hand edits and all):
$ rm -rf lib/bower_components
And reinstall into custom_element_apigen's preferred location:
$ bower install
...
bootstrap#3.1.1 lib/src/bootstrap
└── jquery#2.1.1

apply-author-styles#434679b8da lib/src/apply-author-styles
├── core-ajax#0.3.6
└── polymer#0.3.6
It was ultimately the core-ajax and polymer dependencies that did me in last night. Core-ajax depends on core-xhr, which requires the JavaScript version of Polymer instead of the Dart version. Hopefully custom_element_apigen can work around this.

I add custom_element_apigen to the list of Dart dependencies in my pubspec.yaml:
name: bootstrap_example
dependencies:
  polymer: any
  custom_element_apigen: any
dev_dependencies:
  unittest: any
transformers:
- polymer:
    entry_points:
      - web/index.html
      - test/index.html
Then I get the new dependencies:
$ pub get
Resolving dependencies...
+ custom_element_apigen 0.0.3
Downloading custom_element_apigen 0.0.3...
Changed 1 dependency!
The documentation is upfront about not including much information. It does not even say if the configuration file is generated or created by hand. I try the former:
$ pub run custom_element_apigen:update configfile.yaml
Parsing configuration ... error: file configfile.yaml doesn't exist
OK. I need to build this by hand. Per what documentation there is, I copy the configuration file from core-elements. I start with this:
files_to_generate:
  - apply-author-styles/apply-author-styles.html
Which seems to be what custom_element_apigen wants:
$ pub run custom_element_apigen:update apply_author_styles_gen.yaml
<link rel="import"
^^^^^^^^^^^^^^^^^^
1 of 1: lib/src/apply-author-styles/apply-author-styles.html[Warning from polymer (Linter) on bootstrap_example|lib/src/core-ajax/core-xhr.html]:
line 25, column 1 of lib/src/core-ajax/core-xhr.html: Missing definition for <polymer-element>, please add the following HTML import at the top of this file: <link rel="import" href="../../../../packages/polymer/polymer.html">. See http://goo.gl/5HPeuP#polymer_3 for details.
<polymer-element name="core-xhr" hidden>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Done
I am unsure of those warnings, but I give it a try anyway. In my Polymer.dart element, I replace last night's bower_components attempt:
<link rel="import" href="../../../packages/polymer/polymer.html">
<link rel="import"
      href="../bower_components/apply-author-styles/apply-author-styles.html">
<polymer-element name="pricing-plan">
  <template><-- ... --></template>
  <script type="application/dart" src="pricing_plan.dart"></script>
</polymer-element>
Using instead the custom_element_apigen element:
<link rel="import" href="../../../packages/polymer/polymer.html">
<link rel="import"
      href="../apply_author_styles.html">
<polymer-element name="pricing-plan">
  <template><!-- ... --></template>
  <script type="application/dart" src="pricing_plan.dart"></script>
</polymer-element>
But, when I fire this up in Dartium, I still get:
GET http://localhost:8080/packages/bootstrap_example/core_ajax.html 404 (Not Found) 
It seems that I need to include core-ajax (and core-xhr) in the list of generated files:
files_to_generate:
  - apply-author-styles/apply-author-styles.html
  - core-ajax/core-ajax.html
  - core-ajax/core-xhr.html
After re-running pub run custom_element_apigen:update apply_author_styles_gen.yaml, I again try this in Dartium. Unfortunately, I have no more success this time:
Internal error: 'package:bootstrap_example/core_xhr.dart': error: line 33 pos 29: duplicate formal parameter 'inOptions'
  request(inOptions, String inOptions.url, String inOptions.method, bool inOptions.sync, inOptions.params, inOptions.body, inOptions.headers, String inOptions.responseType, bool inOptions.withCredentials, inOptions.callback) =>
                            ^ 
Bleh. I think it safe to say that I understand why core-xhr in Dart is still hand-written in Dart instead of wrapped by custom_element_apigen. I will call it a night here.

Although unsuccessful in getting apply-author-styles to work, it was nice to get a feel for what custom_element_apigen does. Hopefully in the near future it can also generate a Dart API for core-xhr.


Day #201

4 comments:

  1. I seem to remember something about custom_element_apigen replacing any JS core-elements with the Dart wrapped version, when available. You could try installing core_elements, then rerunning custom_element_apigen, and see where that gets you. Though to be honest, I don't hold much hope for this approach, but it might work, and it might replace core-ajax with core-ajax-dart.

    ReplyDelete
  2. I take that back, it makes no difference. It doesn't replace core-ajax with core-ajax-dart, I just tried with core_elements installed :-(

    ReplyDelete
    Replies
    1. Thanks for trying it out so that I don't have to!

      I may just reimplement it in Dart. The ironic thing is that in Dart, I'd just use HttpRequest instead of core-ajax since Dart has sane Ajax calls. So the very thing that is causing all this fuss (core-xhr) wouldn't even be used in the Dart reimplementation.

      Delete
  3. There's another problem, dart will inline the css, so you can'y just copy link tags, as they will be transformed into style tags. Though if you just inject the link tag at runtime, and then use apply-author-styles, that might work. I'm not sure if that's what you're already doing, as I haven't looked at your implementation thoroughly yet.

    ReplyDelete