How to asynchronously load a google map in AngularJS?

All we need is an easy explanation of the problem, so here it is.

Now that I have found a way to initialize Google Maps with the help of Andy Joslin in this SO initialize-google-map-in-angularjs, I am looking for a way to asynchronous load a Google Map Object.

I found an example of how to do this in the phonecat project.

Notice how the JS files are loaded in this example: index-async.html

In my Jade Scripts partial that is loaded into my program I tried:


    ], function() {
      // when all is done, execute bootstrap angular application
      angular.bootstrap(document, ['ofm']);

When I do this and go to load the map page I get:

A call to document.write() from an asycrononously-loaded 
external script was ignored.

This is how Google Maps is being loaded now as a service:

'use strict';

var app = angular.module('', []);

app.factory('GoogleMaps', function() {

  var map_id  = '#map';
  var lat     = 46.87916;
  var lng     = -3.32910;
  var zoom    = 15;
  var map     = initialize(map_id, lat, lng, zoom);

  return map;

function initialize(map_id, lat, lng, zoom) {
  var myOptions = {
    zoom : 8,
    center : new google.maps.LatLng(lat, lng),
    mapTypeId : google.maps.MapTypeId.ROADMAP
  return new google.maps.Map($(map_id)[0], myOptions);

It appears that this should be returning a promise from what I recall reading. But this AngularJS is very new to me.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

here’s my solution I came up without using jQuery:
(Gist here)

angular.module('testApp', []).
    directive('lazyLoad', ['$window', '$q', function ($window, $q) {
        function load_script() {
            var s = document.createElement('script'); // use global document since Angular's $document is weak
            s.src = '';
        function lazyLoadApi(key) {
            var deferred = $q.defer();
            $window.initialize = function () {
            // thanks to Emil Stenström:
            if ($window.attachEvent) {  
                $window.attachEvent('onload', load_script); 
            } else {
                $window.addEventListener('load', load_script, false);
            return deferred.promise;
        return {
            restrict: 'E',
            link: function (scope, element, attrs) { // function content is optional
            // in this example, it shows how and when the promises are resolved
                if ($ && $ {
                    console.log('gmaps already loaded');
                } else {
                    lazyLoadApi().then(function () {
                        console.log('promise resolved');
                        if ($ && $ {
                            console.log('gmaps loaded');
                        } else {
                            console.log('gmaps not loaded');
                    }, function () {
                        console.log('promise rejected');

Method 2

If you using jQuery in your AngularJS app, check out this function which returns a promise for when the Google Maps API has been loaded:

I was able to use this in a AngularJS directive to lazy-load Google Maps on demand.
Works a treat:

angular.module('mapModule') // usage: data-google-map
    .directive('googleMap', ['$window', function ($window) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                // If Google maps is already present then just initialise my map
                if ($ && $ {
                } else {

                function loadGoogleMapsAsync() {
                    // loadGoogleMaps() == jQuery function from
                        // When Google maps is loaded, add InfoBox - this is optional
                        .then(function () {
                            $.ajax({ url: "/resources/js/infobox.min.js", dataType: "script", async: false });
                        .done(function () {

                function initGoogleMaps() {
                    // Load your Google map stuff here
                    // Remember to wrap scope variables inside `scope.$apply(function(){...});`

Method 3

Take a look of this i think its more reliable

    var deferred = $q.defer();
                        var script = document.createElement('script');

                        $window.initMap = function() {
                            //console.log("Map  init ");

                        script.src = "//";
                        return deferred.promise;

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply