Predator44 Predator44 - 2 months ago 115
AngularJS Question

Why can't I load google maps in angular 2 component?

Here is my ts component:

import {Component, OnInit, Output, EventEmitter} from '@angular/core';

declare var google: any;

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})


export class AppComponent implements OnInit {
title = 'Dashboard';
private map: any;


constructor() {
let brussels = new google.maps.LatLng(50.82, 4.35);
var mapOptions = {
zoom: 9,
center: brussels
};
this.map = new google.maps.Map(document.getElementById('googleMap'), mapOptions);

var marker = new google.maps.Marker({
position: brussels
});
//google.maps.event.addListener(marker, 'click', ( () => this.select.next("i was a map click")) )
marker.setMap(this.map);

}

ngOnInit(){

}


Here is my html:

<h1>
{{title}}
</h1>
<div id="googleMap"></div>
<div id="legend-container"><h3>Legend</h3></div>
<div id="info-box" style="">?</div>


I declared in the main index.html the api key for google maps. The problem is that I cannot seem to load the google map into the component. There errors in the console are mainly the following:

error_handler.js:45 EXCEPTION: Error in ./AppComponent class AppComponent_Host - inline template:0:0 caused by: google is not definedErrorHandler.handleError @ error_handler.js:45(anonymous function) @ application_ref.js:209ZoneDelegate.invoke @ zone.js:192onInvoke @ ng_zone_impl.js:43ZoneDelegate.invoke @ zone.js:191Zone.run @ zone.js:85(anonymous function) @ zone.js:451ZoneDelegate.invokeTask @ zone.js:225onInvokeTask @ ng_zone_impl.js:34ZoneDelegate.invokeTask @ zone.js:224Zone.runTask @ zone.js:125drainMicroTaskQueue @ zone.js:357
error_handler.js:47 ORIGINAL EXCEPTION: google is not definedErrorHandler.handleError @ error_handler.js:47(anonymous function) @ application_ref.js:209ZoneDelegate.invoke @ zone.js:192onInvoke @ ng_zone_impl.js:43ZoneDelegate.invoke @ zone.js:191Zone.run @ zone.js:85(anonymous function) @ zone.js:451ZoneDelegate.invokeTask @ zone.js:225onInvokeTask @ ng_zone_impl.js:34ZoneDelegate.invokeTask @ zone.js:224Zone.runTask @ zone.js:125drainMicroTaskQueue @ zone.js:357
error_handler.js:50 ORIGINAL STACKTRACE:ErrorHandler.handleError @ error_handler.js:50(anonymous function) @ application_ref.js:209ZoneDelegate.invoke @ zone.js:192onInvoke @ ng_zone_impl.js:43ZoneDelegate.invoke @ zone.js:191Zone.run @ zone.js:85(anonymous function) @ zone.js:451ZoneDelegate.invokeTask @ zone.js:225onInvokeTask @ ng_zone_impl.js:34ZoneDelegate.invokeTask @ zone.js:224Zone.runTask @ zone.js:125drainMicroTaskQueue @ zone.js:357
error_handler.js:51 ReferenceError: google is not defined


Any suggestion is highly appreciated :)

Answer

the google maps API is not loaded yet you should load it asynchronously an initialize the map after it has been loaded. take a look at this question about loading google maps asynchronously.

And as @Günter Zöchbauer said you should initialize the map after the view has been initialized. (in ngAfterViewInit)

something like this:

export class AppComponent implements AfterViewInit {
  title = 'Dashboard';
  private map: any;

  constructor() {
  }
  onMapsReady(){
    let brussels = new google.maps.LatLng(50.82, 4.35);
    var mapOptions = {
      zoom: 9,
      center: brussels
    };
    this.map = new google.maps.Map(document.getElementById('googleMap'), mapOptions);
    var marker = new google.maps.Marker({
      position: brussels
    });
    //google.maps.event.addListener(marker, 'click', ( () => this.select.next("i was a map click")) )
    marker.setMap(this.map);
  }
  ngAfterViewInit(){
    (<any>window).googleMapsReady=this.onMapsReady.bind(this);
     var script = document.createElement("script");
    script.type = "text/javascript";
    document.getElementsByTagName("head")[0].appendChild(script);
    script.src = "http://maps.googleapis.com/maps/api/js?v=3&sensor=false&callback=googleMapsReady";

  }

}

NB: loading the API via a service would be (much) better

Comments