TypeError: window.initMap is not a function

AngularjsGoogle MapsGoogle Maps-Api-3

Angularjs Problem Overview


I am following this tutorial, basically copy all the code

https://developers.google.com/maps/documentation/javascript/tutorial

but got an error saying that the initMap function is not a function. I am using angularjs in my project, could that be causing problems?

I copied the same code into plunker and it works just fine... What are the possible issues?

Angularjs Solutions


Solution 1 - Angularjs

Actually the error is being generated by the initMap in the Google's api script

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

so basically when the Google Map API is loaded then the initMap function is executed. If you don't have an initMap function, then the initMap is not a function error is generated.

So basically what you have to do is one of the following options:

  1. to create an initMap function

  2. replace the callback function with one of your own that created for the same purpose but named it something else

  3. replace the &callback=angular.noop if you just want an empty function() (only if you use angular)

Solution 2 - Angularjs

My explanation of this problem:

The .....&callback=initMap" async defer></script> makes that script load async (in parallel with DOM) and after load - execute initMap function. NOTICE that initMap() in global scope! We can't declare our initMap() after google's script because it should already be at the moment of finish async load. Although we can't load our script before this, because we need google's function to execute ours. This is like vicious circle.

Three solutions:

1'st and worst: make google's script load synchronously
  1. remove async defer
  2. remove &callback=initMap in src attribute
  3. put <script tag with your code after google's script
2'nd and best: just do this =)
  1. leave .....&callback=initMap" async defer></script> as is

  2. and put google's <script tag after your script

  3. write in your script

    function initMap() {} // now it IS a function and it is in global
    
    $(() => {
      initMap = function() {
        // your code like...
        var map = new google.maps.Map(document.getElementById('map'), {/*your code*/});
        // and other stuff...
      }
    })
    

this allow you load google's script async and run yours just after that

3'rd and strange: it will work... some times =)
  1. do same but simply write in global scope

    function initMap() {
      // your code
    }
    

and if you write it in global scope, that will work regardless of what which code loads faster, your (sync) or google's (async). More often your wins

Solution 3 - Angularjs

Removing =initMap worked for me:

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

Solution 4 - Angularjs

I have been struggling for several days with this very popular in the last few months issue - "initMap is not a function".

Those two threads helped me:

  1. https://stackoverflow.com/questions/38627259/how-to-make-a-callback-to-google-maps-init-in-separate-files-of-a-web-app?noredirect=1&lq=1

  2. https://stackoverflow.com/questions/22033329/defer-attribute-doesnt-work-with-google-maps-api?noredirect=1&lq=1

Why does the map open sometimes and sometimes not. It depends on several factors like speed of connection, environment, etc. Because the initialization function sometimes runs after the google maps API kicks in, that's why the map is not displayed and the browser console throws an error. For me removing only the async attribute fixed the issue. The defer attribute stays.

If async is present: The script is executed asynchronously with the rest of the page (the script will be executed while the page continues the parsing) If async is not present and defer is present: The script is executed when the page has finished parsing If neither async or defer is present: The script is fetched and executed immediately, before the browser continues parsing the page Source - http://www.w3schools.com/tags/att_script_defer.asp

Hope that helps. Cheers.

Solution 5 - Angularjs

The problem has to do with the async attribute in the script tag. The Callback Function is trying to call "initMap()" when it doesn't really exists by the time the request finished.

To solve this I placed the Goole Maps Api Script bellow the script where my initMap function was declared.

Hope this helps

Solution 6 - Angularjs

This may seem obvious but just in case: If someone placed the JS code inside $(document).ready like this:

     $(document).ready(function() {
       ... Google Maps JS code ...
      }

Then that's the problem because using async defer when loading the Google Maps API library, it will load asynchronously, and when it finishes loading, will look for the callback function, which needs to be available by then.

So, you just need to put the code outside $(document).ready, and:

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

at the very bottom, so your page loads FAST :-)

Solution 7 - Angularjs

Solved by adding

<script async defer
	src="https://maps.googleapis.com/maps/api/js?key=XXXXXXX&callback=initMap">
	<!--
		https://developers.google.com/maps/documentation/javascript/examples/map-geolocation
	-->
</script>

At the beginning of the same file which contains the rest of the code with function initMap(). It's definitely not the best solution, but it works..

But I think that if you would transform function initMap() to something like var=initMap() and then $(function () ... it would work too.

Solution 8 - Angularjs

your call back method probably is not globally accessible. in my case I'd used transpoiled ES6 codes via webpack which caused my callback method not being global anymore.

Try to attach your callback method explicitly to window like so right after your callback method declaration and see the result

window.initMap = initMap;

it worked for me.

Solution 9 - Angularjs

I am using React and I had mentioned &callback=initMap in the script as below

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

then is just removed the &callback=initMap part now there is no such error as window.initMap is not a function in the console.

Solution 10 - Angularjs

Create initMap method between "" tag or load javascript file before call google api.

<script src="Scripts/main.js"></script>

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

Solution 11 - Angularjs

Put this in your html body (taken from the official angular.js website):

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>

I believe that you were using some older angular.js files since you don't have any issues in plunker and therefore you got the specified error.

Solution 12 - Angularjs

For me the main difference was the declaration of the function....

INSTEAD OF

function initMap() {
    ...
}

THIS WORKED

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

Solution 13 - Angularjs

turns out it has to do with ng-Route and the order of loading script wrote a directive and put the API script on top of everything works.

Solution 14 - Angularjs

I had a similar error. The answers here helped me figure out what to do.

index.html

 <!--The div element for the map -->
 <div id="map"></div>

<!--The link to external javascript file that has initMap() function-->
 <script src="main.js">

<!--Google api, this calls initMap() function-->
 <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEYWY&callback=initMap">
</script>

main.js // This gives error


// The initMap function has not been executed
const initMap = () => {
const mapDisplayElement = document.getElementById('map');
  // The address is Uluru
const address = {lat: -25.344, lng: 131.036};
  // The zoom property specifies the zoom level for the map. Zoom: 0 is the lowest zoom,and displays the entire earth.
const map = new google.maps.Map(mapDisplayElement, { zoom: 4, center: address });
const marker = new google.maps.Marker({ position: address, map });
};

The answers here helped me figure out a solution. I used an immediately invoked the function (IIFE ) to work around it.

The error is as at the time of calling the google maps api the initMap() function has not executed.

main.js // This works

const mapDisplayElement = document.getElementById('map');
// The address is Uluru
// Run the initMap() function imidiately, 
(initMap = () => {
  const address = {lat: -25.344, lng: 131.036};
  // The zoom property specifies the zoom level for the map. Zoom: 0 is the lowest zoom,and displays the entire earth.
  const map = new google.maps.Map(mapDisplayElement, { zoom: 4, center: address });
  const marker = new google.maps.Marker({ position: address, map });
})();

Solution 15 - Angularjs

Could be your initMap function is in a $(document).ready function. If it is then it won't work, it has to be outside of any other functions.

Solution 16 - Angularjs

In addition to @DB.Null's answer, I used Function.prototype as no-op (no-operation) function on #3 instead of angular.noop (I don't have angular in my project).

So this...

<script async defer src="https://maps.googleapis.com/maps/api/js?key=API_KEY_HERE&callback=Function.prototype" type="text/javascript"></script>

Solution 17 - Angularjs

In my case there was a formatting issue earlier on, so the error was a consequence of something else. My server was rendering the lat/lon values with commas instead of periods, because of different regional settings.

Solution 18 - Angularjs

I removed the callback of "initMap" from the script tag and placed the callback in my JavaScript file.

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

was changed to

<script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEYWY"></script>

So the first JS tag is mine.

<script async type=module src="js/app.js"></script> <script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEYWY"></script>

I called the initMap function from within my JS file by adding the following to my app.js file.

initMap();

Solution 19 - Angularjs

In my case, I had to load the Map on my Wordpress website and the problem was that the Google's api script was loading before the initMap(). Therefore, I solved the problem with a delay:

<script>
function initMap() {
     // Your Javascript Codes for the map
     ...
}

<?php
// Delay for 5 seconds
sleep(5);
?>

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2901633View Question on Stackoverflow
Solution 1 - AngularjsDB.NullView Answer on Stackoverflow
Solution 2 - AngularjsAndrey KudriavtsevView Answer on Stackoverflow
Solution 3 - AngularjsTomView Answer on Stackoverflow
Solution 4 - AngularjsViktor GeorgievView Answer on Stackoverflow
Solution 5 - AngularjskrlozadanView Answer on Stackoverflow
Solution 6 - AngularjsHugoView Answer on Stackoverflow
Solution 7 - AngularjsvohratomView Answer on Stackoverflow
Solution 8 - AngularjsCode_WormView Answer on Stackoverflow
Solution 9 - AngularjsSamkit ShahView Answer on Stackoverflow
Solution 10 - AngularjsSachith KaushalyaView Answer on Stackoverflow
Solution 11 - AngularjsEugen SunicView Answer on Stackoverflow
Solution 12 - AngularjsThe VojtisekView Answer on Stackoverflow
Solution 13 - Angularjsuser2901633View Answer on Stackoverflow
Solution 14 - AngularjsTamunoibi AprekumaView Answer on Stackoverflow
Solution 15 - AngularjsKNeyView Answer on Stackoverflow
Solution 16 - AngularjsChristopher RegnerView Answer on Stackoverflow
Solution 17 - AngularjsSavageView Answer on Stackoverflow
Solution 18 - AngularjsJohn CollinsView Answer on Stackoverflow
Solution 19 - AngularjsArash DadkhahView Answer on Stackoverflow