Thursday, March 26, 2015

Using the google-map Polymer in Polymer.dart Elements


Thanks to the magic of custom_element_apigen, I was able to use the JavaScript <google-map> Polymer element in a Dart application last night. In the end it was, dare I say it, easy.

Tonight, I would like to dynamically use <google-map> from a custom built Polymer.dart element, let's call it <x-map>. I start by altering my sample page to import this definition instead of directly pulling in the custom_element_apigen version of <google-map>:
<html lang="en">
  <head>
    <script type="application/dart">
      import 'package:my_maps/elements/x_map.dart';
      export 'package:polymer/init.dart';
    </script>
  </head>
  <body unresolved>
    <div class="container">
      <h1>A Simple Map...</h1>
      <x-map latitude="39.283" longitude="-76.616"></x-map>
    </div>
  </body>
</html>
Instead of the usual, boring map of San Francisco, I start with coordinates of a city with some character. In the backing class defined in x_map.dart, I need to support the latitude and longitude attributes. I also need to import the <google-map> element:
@HtmlImport('x-map.html')
library x_map;

import 'package:polymer/polymer.dart';
import '../google_map.dart';

@CustomTag('x-map')
class XMap extends PolymerElement {
  @published float latitude = 0.0;
  @published float longitude = 0.0;

  XMap.created(): super.created();
}
As a side-note, I confess that I am alarmed at how quickly I am getting used to this code-import of Polymer definitions. I have used the <link> imports throughout Patterns in Polymer. It would be hard to switch at this point—especially since the JavaScript version of the book would still have to use <link> imports—but darn these are nice.

At any rate, I import google_map.dart, which is the Dart wrapper generated last night. I also annotate my desired, published attributes. So next up is the HTML template definition.

My first pass at <x-map> is a trivial Polymer template. In it, I bind my latitude and longitude attributes in the <google-map> attributes of the same name:
<polymer-element name="x-map">
  <template>
    <h1>x map</h1>
    <google-map
       latitude="{{latitude}}"
       longitude="{{longitude}}"></google-map>
    <style>
      @import '/packages/my_maps/assets/bootstrap.min.css';
      google-map {
        height: 600px;
      }
    </style>
  </template>
</polymer-element>
I need to style <google-map> lest it display with zero height. With that, I have a working custom Polymer element that itself uses a Google map:



Next up, I would like to verify that I can easily update attributes of <google-map> from my custom element. I could add text fields, but that's dull. Let's try a paper-slider instead.

I update the Dart Pub packaging configuration to include paper elements:
name: my_maps
dependencies:
  polymer: any
  paper_elements: any
dev_dependencies:
  custom_element_apigen: any
transformers:
- polymer:
    entry_points:
    - web/index.html
After a quick pub install I am ready to add a slider to my element. I import it into the backing class:
@HtmlImport('x-map.html')
library x_map;

import 'package:polymer/polymer.dart';
import 'package:paper_elements/paper_slider.dart';
import '../google_map.dart';

@CustomTag('x-map')
class XMap extends PolymerElement {
  // ...
}
Then add it to the HTML template definition:
<polymer-element name="x-map">
  <template>
    <h1>x map</h1>
    <google-map
       latitude="{{latitude}}"
       longitude="{{longitude}}"></google-map>

    <p>
      <paper-slider 
         min="{{longitude - 2}}"
         max="{{longitude + 2}}" 
         value="{{longitude}}"></paper-slider>
    </p>
    <>-- ... -->
  </template>
</polymer-element>
That works brilliantly:



The slider is bound to the longitude of the map, so updating it (as I did above by clicking to the right) updates my element's longitude, which is bound to the <google-map> longitude. The end result is that updating the slider updates the map.

So far, working with <google-map> from Polymer.dart seems quite nice. Up tomorrow, I think that I would like to add custom children to my custom <x-map> such that they act as markers on the map. I have the feeling that the shadow DOM is going to make that a little tricky.


Day #10

3 comments:

  1. Actually making custom elements to act as markers is reasonable straight forward. I did a post which may give you a clue as to how. I'll get back to you with the link to that blog post that explains it.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Ok so it's not about creating custom marker elements, but it does contain the needed clues on how to do this.

    http://terrageek.blogspot.co.nz/2014/08/integrating-dart-googlemaps-package.html

    I was creating a Polygon Overlay element and passed to it via the use of <content> tags a set of lat-lng elements.

    ReplyDelete