You could say that I've forgotten more about Polymer than most programmers will ever know. I would probably agree, but that's just because I have a crap memory.
I was able to get the
<google-map>
JavaScript Polymer element to work in a Polymer.dart context yesterday, but only by hand-editing the JavaScript source files that I had installed via Bower—not at all cool. Happily, James Hurford reminded me that I should be using custom_element_apigen to wrap JavaScript Polymer elements in Dart. I have looked at it in the past, but in my defense, it caused me grief. So maybe it was repression instead of a failing memory. Let's stick with that story, shall we?
I give custom_element_apigen another try tonight by first adding it to the list of development dependencies in my sample application:
name: my_maps dependencies: polymer: any dev_dependencies: custom_element_apigen: any transformers: - polymer: entry_points: - web/index.htmlI have to update the location in which Bower installs its packages so that custom_element_apigen can find the elements that I want to use in my Dart application. So I modify the
.bowerrc
configuration file to install everything in lib/src
:{ "directory": "lib/src" }Installing now places these dependencies in
lib/src
as desired:$ bower install ... polymer#0.5.1 lib/src/polymer ├── core-component-page#0.5.5 └── webcomponentsjs#0.5.1 google-map#0.4.1 lib/src/google-map └── google-apis#0.4.4 webcomponentsjs#0.5.1 lib/src/webcomponentsjs core-component-page#0.5.5 lib/src/core-component-page ├── polymer#0.5.1 └── webcomponentsjs#0.5.1 google-apis#0.4.4 lib/src/google-apis └── core-shared-lib#0.5.5 core-shared-lib#0.5.5 lib/src/core-shared-lib └── polymer#0.5.1With that, I am ready to create a configuration file for custom_element_apigen. The project is still woefully (and self-admittedly) under-documented. Thankfully, I still have my old configuration file from the last time, so I adapt it for
<google-map>
. I save the following in apigen.yaml
:files_to_generate: - google-map/google-map.htmlI then run the generate command. In addition to lack of documentation, it also lacks output. Even so, it does not take too much work to find the generated files:
$ pub run custom_element_apigen:update apigen.yaml Done $ ls -ltr lib total 32 drwxr-xr-x 2 chris chris 4096 Mar 24 23:57 assets drwxr-xr-x 2 chris chris 4096 Mar 25 23:04 elements drwxr-xr-x 8 chris chris 4096 Mar 25 23:04 src -rw-r--r-- 1 chris chris 114 Mar 25 23:07 google_map_nodart.html -rw-r--r-- 1 chris chris 164 Mar 25 23:07 google_map.html -rw-r--r-- 1 chris chris 9065 Mar 25 23:07 google_map.dartBased on the
nodart
file, it seems that custom_element_apigen supports both the new and old style importing approaches. In my sample application page, I opt for the new, code-import style:<!doctype html> <html lang="en"> <head> <script type="application/dart"> import 'package:my_maps/google_map.dart'; export 'package:polymer/init.dart'; </script> </head> <body unresolved> <google-map latitude="37.779" longitude="-122.3892" minZoom="9" maxZoom="11" fit></google-map> </body> </html>When I try to run my simple application,
pub serve
reports:[Error from polymer (PolymerBootstrapTransformer) on my_maps|web/index.html]: Could not load asset my_maps|lib/google_maps_api.dart [Warning from polymer (PolymerBootstrapTransformer) on my_maps|web/index.html]: line 2, column 1 of lib/google_map_nodart.html: Failed to inline HTML import: Could not find asset my_maps|lib/google_maps_api_nodart.html. null. See http://goo.gl/5HPeuP#web_components_4 for details. <link rel="import" href="google_maps_api_nodart.html"> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^So I update my
apigen.yaml
file to include this element from the Bower-installed JavaScript dependency:files_to_generate: - google-map/google-map.html - google-apis/google-maps-api.htmlI re-run
pub run custom_element_apigen:update apigen.yaml
, restart pub serve
, and it fails again. This time with a different element. I repeat this process until my agigen.yaml
file contains:files_to_generate: - google-map/google-map.html - google-apis/google-maps-api.html - core-shared-lib/core-shared-lib.htmlI again re-run
pub run custom_element_apigen:update apigen.yaml
, again restart pub serve
, and finally, I have a working <google-map>
in a Polymer.dart application:Nice.
I had used explicit Bower dependencies last night in a attempt to eliminate
webcomponentjs.js
incompatibilities between my Polymer.dart code and my Polymer.js elements:{ "name": "my-maps", "dependencies": { "google-map": "GoogleWebComponents/google-map#0.4.1", "polymer": "Polymer/polymer#0.5.1", "webcomponentsjs": "Polymer/webcomponentsjs#0.5.1" } }I relax those dependencies now:
{ "name": "my-maps", "dependencies": { "google-map": "GoogleWebComponents/google-map#~0.4.2", "polymer": "Polymer/polymer#~0.5.5", "webcomponentsjs": "Polymer/webcomponentsjs#~0.5.5" } }After a re-install of the Bower dependencies, I have:
$ bower install ... webcomponentsjs#0.5.5 lib/src/webcomponentsjs google-map#0.4.2 lib/src/google-map polymer#0.5.5 lib/src/polymer ...Polymer.dart bundles version 0.5.1 of
webcomponentsjs
so this could cause problems. Without re-running the apigen command, I try to load my application. Pub generates it OK, but it does not work in the browser and I see similar error messages in the console as I saw last night:Uncaught HierarchyRequestError: Failed to execute 'appendChild' on 'Node': Nodes of type 'HTML' may not be inserted inside nodes of type '#document'.Hopefully custom_element_apigen is smart enough to resolve this. I re-run the generate command:
$ pub run custom_element_apigen:update apigen.yaml DoneAfter restarting
pub serve
I find that the application is working again. Yay! Forcing
webcomponentsjs
dependencies would have been a significant pain had that not worked—especially if it prevented the use of newer JavaScript custom elements in Polymer.dart. Thankfully the custom_element_apigen package has me covered.Happily, this worked out much better for me than my last attempt at working with custom_element_apigen. I still need to experiment with using the generated elements in other elements (material for tomorrow). But this is promising. It would be nice if the generator were a little more helpful about the files that need to be generated, but this was not too bad.
There is an outside chance that I may even remember custom_element_apigen in 6 months!
Day #9
"There is an outside chance that I may even remember custom_element_apigen in 6 months!"
ReplyDeleteI doubt it. I have enough trouble remembering things I don't use all the time myself. So unless you end up using custom_element_apigen a lot in the next few months, you'll probably forget, like all good developers :-)
This comment has been removed by the author.
ReplyDeleteGreat post!
ReplyDeleteI would like a Paper Datatable in Dart. We have an nice implementation in JavaScript here: https://github.com/David-Mulder/paper-datatable.
I did not have success with Custom Element Apigen for this component.
If possible, it would be interesting to see a post on this component Paper Datatable. I think that would help many people!