title: Error when trying to render Google Map on page
body: <h3>The Question</h3>
  
  <p>I am trying to create a custom implementation of the Google Maps using the API in Angular 2 and TypeScript. I have everything working up to the part where the map should be getting rendered on the page.</p>
  
  <p>Unfortunately, the map renders as a blank gray square, and attempting to interact with it leads to a very nondescript <code>Cannot read property 'x' of undefined</code> error.</p>
  
  <p>I have read in several other questions on the site that this is usually due to the map attempting to render into a hidden DOM element, load into a DOM element that doesn't exist (not in a page-load function), or that it loses reference to the DOM element it was rendered into.</p>
  
  <p>From what I can see here, I have satisfied all of those conditions, unless I am missing something about the way Angular is working here?</p>
  
  <p>Can somebody please point me in the right direction here?</p>
  
  <h3>The Code</h3>
  
  <pre><code>declare let google: any;
  
  /**
   * @Component: Map
   * @Section: Miscellaneous
   * @Description: Generates an interactive map
   */
  @Component({
      selector: 'mymap',
      template: `&lt;div #map style="min-width:600px; min-height: 600px;"&gt;&lt;/div&gt;`
  })
  export class MyMapComponent {
  
      // A reference to the map DOM element
      @ViewChild("map") mapEl: ElementRef;
  
      // A reference to the map object
      map: any;
  
      // Intializes the map
      initMap: Function = function(){
  
          // Set the map to a new google map
          this.map = new google.maps.Map(this.mapEl.nativeElement, {
  
              // Default zoom level
              zoom: this.zoomLevel | 6
          })
  
          console.log(this.map);
      };
  
      // Sets the center of the map
      setMapCenter: Function = function( latlng: any ){
          if ( this.map &amp;&amp; latlng ){
              this.map.setCenter();
          }
      }
  
      // Callback for the call to the browser to request the users estimated lat/lng
      getUserLocationCallback: any = function( position: any ){
  
          // Catches a Geoposition object:
          // coords
          //  - accuracy
          //  - altitude
          //  - altitudeAccuracy
          //  - heading
          //  - latitude
          //  - longitude
          //  - speed
          // timestamp
          this.setMapCenter(new google.maps.LatLng({lat: position.coords.latitude, lng: position.coords.latitude}));
      }
  
      // On Init
      ngAfterViewInit(){
  
          // Set the key for the Google Maps API
          var gmap_api_key = "[KEY_REMOVED]";
  
          // Create the script tag and add it to the document
          var gmap = document.createElement('script');
          gmap.type = 'text/javascript';
          gmap.async = true;
          gmap.src = "https://maps.googleapis.com/maps/api/js?key=" + gmap_api_key;
          var s = document.getElementsByTagName('script')[0];
          s.parentNode.insertBefore(gmap, s);
  
          // Wait for the script to load
          var mapsInterval = setInterval( () =&gt; {
  
              // If the script is loaded and the maps functions are available
              if ( typeof google !== "undefined" &amp;&amp; google.maps &amp;&amp; google.maps.Map){
  
                  // Clear our interval
                  clearInterval(mapsInterval);
  
                  // Initialize the map
                  this.initMap();
  
                  // Request location from the browser. Arrow function used to maintain scope.
                  navigator.geolocation.getCurrentPosition( () =&gt; { this.getUserLocationCallback } );
              }
          }, 0);
      }
  
      /**
       * @Property: displayedMarkers
       * @Description: A list of markers current displayed on the map.
       * @Type: array
       * @Two-way: output only
       */
      @Output() displayedMarkersChange: EventEmitter&lt;any[]&gt; = new EventEmitter;
  
      /**
       * @Property: mapCenter
       * @Description: lat/long of the center of the map being displayed
       * @Type: object {lat: "N", lng: "N"}
       * @Two-way: true
       */
      @Input()
      set mapCenter( position: any ){
  
          // If a position was provided
          if ( typeof position !== "undefined" ){
  
              // Set thet map center using the provided position
              this.setMapCenter( new google.maps.LatLng (position ) );
          }
      }
      @Output() mapCenterChange: EventEmitter&lt;any[]&gt; = new EventEmitter;
  
      /**
       * @Property: zoomLevel
       * @Description: Current zoom level of the map. Accepts values between 0 (shows the entire earth) and up 21
       * @Type: array
       * @Two-way: true
       */
      @Input() zoomLevel: number;
      @Output() zoomLevelChange: EventEmitter&lt;number&gt; = new EventEmitter;
  
      /**
       * @Property: filters
       * @Description: Filters to be applied to the marker results.
       * @Type: array
       * @Two-way: false
       */
      @Input() filters: any[];
  } 
  </code></pre>
  
  <h3>The Plunkr</h3>
  
  <p><a href="https://plnkr.co/edit/pIVOCSJ5eb1PUVXoEffS?p=preview" rel="nofollow noreferrer">https://plnkr.co/edit/pIVOCSJ5eb1PUVXoEffS?p=preview</a></p>