Up tonight, I would like to muck around with custom, Google Map-like, Polymer.dart elements. Thanks to the custom_element_apigen, I can pull the JavaScript
<google-map>
element into Dart code. It also pulls in <google-map-marker>
and other, related elements. I can even individually use them in custom-built Polymer elements. But what about together?Specifically, what if I wanted to mark up my
<x-map>
Polymer.dart element (powered by <google-map>
) with <x-meetup>
marker elements (powered by <google-map-marker>
)? That is, I would the following to result in a map with the venerable B'more on Rails meetup displayed: <x-map latitude="39.283" longitude="-76.616">
<x-meetup
name="B'more on Rails"
url="http://bmoreonrails.org"
latitude="39.2810662"
longitude="-76.5808788"></x-meetup>
</x-map>
I think this is going to be tricky for two reasons. First, the <google-map>
element is rendering in the shadow DOM of <x-map>
:Similarly, the
<google-map-marker>
element in <x-meetup>
would reside in the shadow DOM of <x-meetup>
. How on earth do I get the <google-map>
and <google-map-marker>
on the same document fragment, let alone working together? The second thing that makes this tricky is that
<x-meetup>
resides in the light DOM of the document and is projected into <x-map>
. The problem there is that, to the best of my knowledge, there is no easy way to get distributed nodes in Polymer.dart.It turns out that I do not have to worry about distributed nodes in this case. Instead, once the container
<x-map>
element is attached to the document, I can iterate over the children:@HtmlImport('x-map.html') library x_map; import 'package:polymer/polymer.dart'; import '../google_map.dart'; import 'x_meetup.dart'; @CustomTag('x-map') class XMap extends PolymerElement { // ... XMap.created(): super.created(); attached(){ children.forEach((el){ // Add markers from each child the map... }); } }I am unsure how best to grab the
<google-map-marker>
from the children. It seems wrong to root through a child's shadow DOM. So instead, I assume the element has a googleMapMarker
property that exposes this element (likely as part of a mixin):@CustomTag('x-map') class XMap extends PolymerElement { // ... XMap.created(): super.created(); Element get map => $['google-map']; attached(){ children.forEach((el){ var marker = el.googleMapMarker.clone(true); map.append(marker); }); } }Once I have the marker, I clone it so that it can be added to the
<x-map>
shadow root.The
map
getter finds the <google-map>
via dollar sign lookup of the google-map
ID:<polymer-element name="x-map"> <template> <h1>x map</h1> <google-map id="google-map" latitude="{{latitude}}" longitude="{{longitude}}"></google-map> </template> </polymer-element>As for the
<x-meetup>
element that has a <google-map-marker>
element, I define the attributes and the googleMapMarker
getter in x_meetup.dart
as:@HtmlImport('x-meetup.html') library x_map; import 'package:polymer/polymer.dart'; import '../google_map.dart'; @CustomTag('x-meetup') class XMeetup extends PolymerElement { @published String name; @published String url; @published float latitude = 0.0; @published float longitude = 0.0; @published Element map; XMeetup.created(): super.created(); Element get googleMapMarker => $['marker']; }Finally the
x-meetup.html
template builds the <google-map-marker>
element as:<polymer-element name="x-meetup"> <template> <google-map-marker id="marker" map="{{map}}" latitude="{{latitude}}" longitude="{{longitude}}" title="{{name}}" labelContent="{{name}}" labelClass="labels"> <p>This is... <a href="{{url}}">{{name}}</a></p> </google-map-marker> </template> </polymer-element>The class looks this element up via the
marker
ID, returns it back to the <x-map>
class, which clones it and inserts it in the <x-map>
element's <google-map>
. The end result is a marker showing where B'more on Rails meets:This might be somewhat contrived, but it does have the advantage of taking what could be consistent data for a bunch of meetups:
<x-meetup
name="B'more on Rails"
url="http://bmoreonrails.org"
latitude="39.2810662"
longitude="-76.5808788"></x-meetup>
And presenting it in a consistent way on the map. For instance, thanks to the <p>
tag in the <x-meetup>
template:<polymer-element name="x-meetup"> <template> <google-map-marker id="marker" map="{{map}}" latitude="{{latitude}}" longitude="{{longitude}}" title="{{name}}" labelContent="{{name}}" labelClass="labels"> <p>This is... <a href="{{url}}">{{name}}</a></p> </google-map-marker> </template> </polymer-element>These meetup markers get a nifty little info window:
There may be better ways to go about accomplishing this, but in the end, a fairly minimal amount of code produced some nice markers on a custom map. That is a nice win.
Day #11
Just shows assumptions can get you in trouble, but oh well. I never knew you could access child elements without going through the <content> tag. It never occurred to me to check if you could. Thanks for simplifying my life for me :-)
ReplyDeleteIts nice.You can check mine too. Its regarding google maptags. Maptags shortens your address to your favourite word and makes sharing address as easy as sharing a word. Visit at mapta.gs/maptags/700110
ReplyDelete