Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass array and/or object data between Polymer elements

I'm setting up a custom google maps Polymer element called "locator-map" that uses polymer-jsonp to grab data from a google spreadsheet, take the response, and send it off to a custom "google-map" element to plot the markers on the map. I can't seem to figure out how to actually inject the data coming back from the polymer-jsonp element into my google-map element so that it can use it to construct the markers.

Here's my data source: https://spreadsheets.google.com/feeds/list/0Ao_YrKZEsc4AdGppeG1zaGotRDd0LUdIYk9tdW9VZnc/od6/public/values?alt=json-in-script

I followed directions here to set this up initially: http://www.html5rocks.com/en/tutorials/webcomponents/yeoman/

Code for my locator-map element:

<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/polymer-jsonp/polymer-jsonp.html">
<link rel="import" href="google-map.html">

<polymer-element name="locator-map" attributes="">
  <template>
      <style>
          /* styles for the custom element itself - lowest specificity */
          :host { display: block; }
          google-map {
              display:block;
              height:600px;
          }
      </style>

      <!-- Load Data with JSONP Endpoint (in this case Google Spreadsheets)
          Format: https://spreadsheets.google.com/feeds/list/0AhcraNy3sgspdDhuQ2pvN21JVW9NeVA0M1h4eGo3RGc/od6/public/values?alt=json-in-script&callback=
          Source: https://docs.google.com/spreadsheet/ccc?key=0AqZBbhllhMtHdFhFYnRlZk1zMzVZZU5WRnpLbzFYVFE&usp=sharing
      -->
      <polymer-jsonp auto url="https://spreadsheets.google.com/feeds/list/0Ao_YrKZEsc4AdGppeG1zaGotRDd0LUdIYk9tdW9VZnc/od6/public/values?alt=json-in-script&callback=" response="{{locations}}"></polymer-jsonp>

      <ul>
          <template repeat="{{location in locations.feed.entry}}">
              <li>Name: {{location.gsx$name.$t}}
                <ul><li>Lat: {{location.gsx$lat.$t}}</li><li>Long: {{location.gsx$lng.$t}}</li></ul>
              </li>
          </template>
      </ul>

      <!-- Load the Google Map -->
      <google-map map="{{map}}" latitude="45.526158" longitude="-122.679394" zoom="14" markers="{{locations}}"></google-map>

  </template>
  <script>
    Polymer('locator-map', {
      // element is fully prepared
      ready: function(){
      },
      // instance of the element is created
      created: function() { },
      // instance was inserted into the document
      enteredView: function() { },
      // instance was removed from the document
      leftView: function() { },
      // attribute added, removed or updated
      attributeChanged: function(attrName, oldVal, newVal) { }
    });
  </script>
</polymer-element>

Code for my google-map element:

<link rel="import" href="../bower_components/polymer/polymer.html">

<polymer-element name="google-map" attributes="latitude longitude zoom showCenterMarker map markers">
    <template>
        <style>
            :host {
                position: relative;
            }

            #map {
                position: absolute;
                top: 0;
                right: 0;
                bottom: 0;
                left: 0;
            }
        </style>

        <div id="map"></div>
    </template>
    <script>
        (function() {
            var CALLBACK_NAME = 'polymer_google_map_callback';
            var MAP_URL = 'https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places&sensor=false&callback=' + CALLBACK_NAME;
            var pendingCallbacks = [];
            var loading;

            function loadMapApi(callback) {
                if (window.google && window.google.maps) {
                    callback();
                    return;
                }
                if (!loading) {
                    loading = true;
                    window[CALLBACK_NAME] = mapApiLoaded.bind(this);
                    var s = document.createElement('script');
                    s.src = MAP_URL;
                    document.head.appendChild(s);
                }
                pendingCallbacks.push(callback);
            }

            function mapApiLoaded() {
                delete window[CALLBACK_NAME];
                pendingCallbacks.forEach(function(callback) {
                    callback();
                });
            }

            Polymer('google-map', {
                latitude: '37.77493',
                longitude: '-122.41942',
                zoom: 10,
                showCenterMarker: false,
                observe: {
                    latitude: 'updateCenter',
                    longitude: 'updateCenter'
                },
                ready: function() {
                    loadMapApi(this.mapReady.bind(this));
                },
                created: function() {
                },
                enteredView: function() {
                    this.resize();
                },
                mapReady: function() {

                    // Create the Map
                    this.map = new google.maps.Map(this.$.map, {
                        zoom: this.zoom,
                        center: new google.maps.LatLng(this.latitude, this.longitude)
                    });

                    // Show Center Marker
                    this.showCenterMarkerChanged();

                    // Add Markers (if any supplied)
                    this.addMarkers();

                    // Fire the Map Ready Event
                    this.fire('google-map-ready');
                },
                resize: function() {
                    if (this.map) {
                        google.maps.event.trigger(this.map, 'resize');
                        this.updateCenter();
                    }
                },
                updateCenter: function() {
                    if (!this.map) {
                        return;
                    }
                    this.map.setCenter(
                            new google.maps.LatLng(this.latitude, this.longitude));
                    this.showCenterMarkerChanged();
                },
                zoomChanged: function() {
                    if (this.map) {
                        this.map.setZoom(Number(this.zoom));
                    }
                },
                showCenterMarkerChanged: function() {
                    if (!this.map) {
                        return;
                    }
                    if (!this.centerMarker && this.showCenterMarker) {
                        this.centerMarker = new google.maps.Marker({
                            map: this.map
                        });
                    }
                    if (this.centerMarker) {
                        this.centerMarker.setPosition(this.map.getCenter());
                        this.centerMarker.setMap(this.showCenterMarker ? this.map : null);
                    }
                },

                /*
                 * Add Markers
                 * Adds markers to the map.  Expects an array of objects specifying the location information via name, lat and lng properties.
                 *
                 * @author erikharper
                 */
                addMarkers: function()
                {
                    console.log("Markers: ");
                    console.log(this.markers);

                    // Get the Map instance
                    var map = this.map;

                    if(this.markers.isArray())
                    {
                        // Create each Marker on the Map
                        this.markers.forEach(function(marker){

                            // Create a LatLng object
                            var markerLatLng = new google.maps.LatLng(marker.lat, marker.lng);

                            // Create the Marker object and add it to the map via the map property
                            new google.maps.Marker({
                                map: map,
                                position: markerLatLng,
                                title: marker.name
                            });
                        });
                    }

                }

            });
        })();
    </script>
</polymer-element>

On my console I get a "this.markers is null". What am I doing wrong?

like image 249
eriklharper Avatar asked Apr 04 '14 00:04

eriklharper


People also ask

What is the recommended method of mutating an array in polymer JS?

You must use these methods when mutating an array to ensure that any elements watching the array (via observers, computed properties, or data bindings) are kept in sync. Every Polymer element has the following array mutation methods available: push( path , item1 , [..., itemN ]) pop( path )

What supports both upward and downward data flow?

Double-curly brackets ( } ) support both upward and downward data flow.


1 Answers

You have markers="{{locations}}", which is the pure JSON response from the polymer-jsonp component. I had to transform the data and parse the lat/lng first:

var markers = [];
markers.push({
  lat: parseFloat(entry.gsx$lat.$t),
  lng: parseFloat(entry.gsx$lng.$t),
  name: entry.gsx$name.$t
});
this.markers = markers;

The way I approached was to reuse the existing Polymer google-map element: http://jsbin.com/wowuledo/6/edit

The important bit is that when the this.markers array changes, markersChanged gets called, which in turn calls your addMarkers (which I modified):

  markersChanged: function() {
    this.addMarkers();
  },
  addMarkers: function() {
    this.markers.forEach(function(marker) {
      var marker = new google.maps.Marker({
        map: this.map,
        position:  new google.maps.LatLng(marker.lat, marker.lng),
        title: marker.name
      });
    }.bind(this));
  }

If you must create an additional element to add your own properties/methods to, why not inherit from google-maps?

<polymer-element name="google-map-with-markers" extends="google-map" attributes="markers">

This way, you get all the functionality from google-maps, but can data-bind to the markers published property:

<google-map-with-markers latitude="45.526158" longitude="-122.679394" zoom="14" markers="{{markers}}"></google-map-with-markers>

Try: http://jsbin.com/renuyifu/1/edit

like image 138
ebidel Avatar answered Nov 10 '22 04:11

ebidel