Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a callback to Google Maps init in separate files of a web app

When I had my Google Maps API snippet:

<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script>

in index.html, I got the error:

Uncaught InvalidValueError: initMap is not a function

I want to keep all of my bower_component, CSS, API, and script declarations in my index.html file on my Yeoman-scaffolded AngularJS web app. The map I was actually trying to recreate would be on another route, let's call it route "afterlogin", just a basic map. I separated the js and the html html components into afterlogin.js and afterlogin.html

There are a number of potential causes for this. One of which was presented here as a matter of adjusting the call to match the namespace, https://stackoverflow.com/a/34466824/1923016 . Would this require an angular service? If so, how would the service work into the initMap function and its call in the Google maps api snippet?

One of the complications is the order. I'm new to web app dev, but from what I can tell the index.html loads first, uses the url in the snippet to make the callback to the initMap function which is not featured in <script>...</script> in the index.html file nor in the app.js file. Instead, since the init function is in a route's js code, it cannot be seen, hence the need for some kind of "namespace" version of the call. This leads to a console error even from the login route, which is not even where the div for the map is.

---- EDIT: ----

Also note that in this case, this did not do the trick:

window.initMap = function(){
//...
}

This also does not apply, as the function is never called: Uncaught InvalidValueError: initMap is not a function

-- -- -- -- -- --

afterlogin.js

angular.module('myappproject').controller('AfterloginCtrl', function ($scope) {

  function initMap() {
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 17,
      center: {lat: -33.8666, lng: 151.1958}
    });

    var marker = new google.maps.Marker({
      map: map,
      // Define the place with a location, and a query string.
      place: {
        location: {lat: -33.8666, lng: 151.1958},
        query: 'Google, Sydney, Australia'

      },
      // Attributions help users find your site again.
      attribution: {
        source: 'Google Maps JavaScript API',
        webUrl: 'https://developers.google.com/maps/'
      }
    });

    // Construct a new InfoWindow.
    var infoWindow = new google.maps.InfoWindow({
      content: 'Google Sydney'
    });

    // Opens the InfoWindow when marker is clicked.
    marker.addListener('click', function() {
      infoWindow.open(map, marker);
    });
  }
 });

afterlogin.html

<!DOCTYPE html>
<html>
    <head>
        <title>after login page</title>
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
        <meta charset="utf-8">
        <style>
            html, body {
                height: 100%;
                margin: 0;
                padding: 0;
                }
            #map {
                height: 100%;
            }
        </style>
    </head>
    <body>

        <div id="map"></div>
        
    </body>
</html>
like image 611
AlleyOOP Avatar asked Jul 28 '16 04:07

AlleyOOP


1 Answers

I could fix it in my code by using the callback and declaring the initMaps function on window as you did:

window.initMap = function(){
  //...
}

However, the trick was to load my custom JS (which also includes the above declaration of initMaps) before loading Google Maps:

<script async src="myCustomJsInclduingInitMapsFunction.js"></script>
<script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script>

Hope this helps.

like image 69
morgler Avatar answered Sep 26 '22 08:09

morgler