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