0

I've created this javascript (delivery.js) that is supposed to take a pre-existing div on a webform page and append a Google Map to it, along with a few circles of differing radius.

Here is my libraries.yml, I reference the GoogleMaps global in the script url to be used as the callback.

delivery:
  version: 1.x
  js:
    js/delivery.js: {}
  dependencies:
  - core/jquery
  - core/drupalSettings
maps:
  js:
    'https://maps.googleapis.com/maps/api/js?key=AIzaSyCP9_LHyWKv821WTcLWZd8GcLLHIHvPPU0&callback=GoogleMaps.initMap&v=weekly':  { type: external, minified: true }

.module file attaching the libraries:

function order_form_webform_handler_form_alter(&$form, &$form_state, $form_id) {
    if($form_id == "webform_submission_order_submission_node_5_add_form" || $form_id == "webform_submission_order_submission_test_form" ){
        $form['#attached']['library'][] = 'order_form_webform_handler/delivery';
        $form['#attached']['library'][] = 'order_form_webform_handler/maps';
    }
}

Finally, my delivery.js file that does all the work:

var GoogleMaps = GoogleMaps || {};
(function ($, Drupal, GoogleMaps) {
  
    Drupal.behaviors.attachMap = {
      attach: function () {

        GoogleMaps.initMap = function(){
          // Create the map.
          const map = new google.maps.Map(document.getElementById("edit-map"), {
            zoom: 4,
            center: { lat: 44.24, lng: -76.57 },
            mapTypeId: "terrain",
          });

          let radii = [10000, 15000, 20000, 30000];

          for(let i = 0; i < radii.length; i++){
            const cityCircle = new google.maps.Circle({
              strokeColor: "#FF0000",
              strokeOpacity: 0.8,
              strokeWeight: 2,
              fillColor: "#FF0000",
              fillOpacity: 0.35, 
              map: map,
              center: { lat: 44.24, lng: -76.57 },
              radius: radii[i],
            });
          }
        }
      }
    };
  
  })(jQuery, Drupal, GoogleMaps);

However, when I try to run this, I get this error:

.te {message: 'GoogleMaps.initMap is not a function', stack: 'Error\n at _.te.captureStackTrace (https://maps.PPU0&callback=GoogleMaps.initMap&v=weekly:212:276', name: 'InvalidValueError'}

Is there a better method of invoking the callback that I don't know about?

3 Answers 3

0

You will need to ensure your library is loaded first, by creating it as a dependency of the first library:

delivery:
  version: 1.x
  js:
    js/delivery.js: {}
  dependencies:
  - core/jquery
  - core/drupalSettings

maps:
  js:
    'https://maps.googleapis.com/maps/api/js?key=AIzaSyCP9_LHyWKv821WTcLWZd8GcLLHIHvPPU0&callback=GoogleMaps.initMap&v=weekly':  { type: external, minified: true }
  dependencies:
  - order_form_webform_handler/delivery
6
  • Ok, I removed the GoogleMaps declaration line, but now it saying GoogleMaps is not defined. Where would be the best place to declare this variable if I need it to store this function?
    – Riley Lutz
    Commented Nov 29, 2022 at 21:04
  • Sorry, I misunderstood your original post. I've updated my post.
    – Jaypan
    Commented Nov 29, 2022 at 21:11
  • It's all good. I edited the libraries.yml to what you posted, but it's still giving the "GoogleMaps.initMap is not a function" error from my original post.
    – Riley Lutz
    Commented Nov 29, 2022 at 21:23
  • You have a couple options. Remove the anonymous wrapper and Drupal.behaviors, as GoogleMaps.init() will not exist until Drupal.behaviors is called, or, you can dynamically load the google maps script with JS instead of using libraries.
    – Jaypan
    Commented Nov 29, 2022 at 21:40
  • Oh man, so that was affecting it! Getting rid of the inner attached anon function fixed it, now the maps showing up, thank you!
    – Riley Lutz
    Commented Nov 29, 2022 at 21:48
0

I've finally managed to hobble this together in a working manner for me:

my_module.libraries.yml:

my_module:
  version: 1.x
  js:
    js/my-module.js: {}
  dependencies:
    - core/jquery
    - my_module/maps
maps:
  js:
    //maps.googleapis.com/maps/api/js?key=[APIKEY]&callback=Function.prototype&libraries=places&v=weekly: { type: external, minified: true }

In the my_module.module file, I'm attaching the library in a hook_form_alter, but you may attach it in whatever function suits you...

$form['#attached']['library'][] = 'my_module/maps';
$form['#attached']['library'][] = 'my_module/my_module';

my-module.js:

// Initialize GoogleMaps object
let GoogleMaps = google.maps || {};

(function ($, Drupal, GoogleMaps) {

  Drupal.behaviors.myModuleMapsBehavior = {
    attach: function (context, settings) {

      GoogleMaps.fillInAddress = function () {
        console.log('fillInAddress');
        /* do something */
      };

      GoogleMaps.initMap = function () {
        console.log('initMap');
        GoogleMaps.fillInAddress();
        /* do something */
      };

      GoogleMaps.initMap();
    }
  };

})(jQuery, Drupal, GoogleMaps);

In the libraries file, I used the Function.prototype callback as described here: https://stackoverflow.com/a/75212692/1541757

In the first line of the js file, I had to change:

let GoogleMaps = GoogleMaps || {};

To ...

let GoogleMaps = google.maps || {};

I'm unsure if this is a Google API change or what, but this is working for me so far.

-1

Found the fix, the attach: function(....) wrapper line was affecting the visibility of the initMap function. Removing that cleared the error. Dynamically loading the script with JS would work as well, but did not get to a point where I tried testing that.

1
  • Could someone please tell me why this is being downvoted? Is my description of the fix not descriptive enough?
    – Riley Lutz
    Commented Nov 30, 2022 at 22:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.