ACF & Google Maps API

Hello,

I’m trying to add a Google Map on my WordPress site using ACF, without success. This error shows up: “map is assigned a value but never used”

I created a new JS route called contact.js where I put the JS code found on the ACF docs.

And this is the code on my template contact page:

    <div class="gmap">
      <div class="marker" data-lat="<?php echo $location['lat']; ?>" data-lng="<?php echo $location['lng']; ?>"></div>
    </div>

I also insert this in my setup.php file:

function add_scripts() {
    wp_enqueue_script('google-maps', 'https://maps.googleapis.com/maps/api/js?key=my_key', [], null, true);
  }
  add_action('wp_enqueue_scripts',  __NAMESPACE__ . '\\add_scripts');

What did I missed ?

Thanks for your help.

What is your assets/scripts/routes/contact.js content?

You can disable no-unused-vars from eslint:

$(function initMap() { // eslint-disable-line no-unused-vars

I already disabled no-unused-vars from eslint. This is the content of contact.js:

/* eslint-disable no-unused-vars */

import google from 'google';

export default {
  init() {
    // JavaScript to be fired on the home page
  },
  finalize() {
    // JavaScript to be fired on the home page, after the init JS

    (function($) {

      /*
      *  new_map
      *
      *  This function will render a Google Map onto the selected jQuery element
      *
      *  @type	function
      *  @date	8/11/2013
      *  @since	4.3.0
      *
      *  @param	$el (jQuery element)
      *  @return	n/a
      */

      function new_map( $el ) {

        // var
        var $markers = $el.find('.marker');


        // vars
        var args = {
          zoom		: 16,
          center		: new google.maps.LatLng(0, 0),
          mapTypeId	: google.maps.MapTypeId.ROADMAP,
        };


        // create map
        var map = new google.maps.Map( $el[0], args);


        // add a markers reference
        map.markers = [];


        // add markers
        $markers.each(function(){

            add_marker( $(this), map );

        });


        // center map
        center_map( map );


        // return
        return map;

      }

      /*
      *  add_marker
      *
      *  This function will add a marker to the selected Google Map
      *
      *  @type	function
      *  @date	8/11/2013
      *  @since	4.3.0
      *
      *  @param	$marker (jQuery element)
      *  @param	map (Google Map object)
      *  @return	n/a
      */

      function add_marker( $marker, map ) {

        // var
        var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') );

        // create marker
        var marker = new google.maps.Marker({
          position	: latlng,
          map			: map,
        });

        // add to array
        map.markers.push( marker );

        // if marker contains HTML, add it to an infoWindow
        if( $marker.html() )
        {
          // create info window
          var infowindow = new google.maps.InfoWindow({
            content		: $marker.html(),
          });

          // show info window when marker is clicked
          google.maps.event.addListener(marker, 'click', function() {

            infowindow.open( map, marker );

          });
        }

      }

      /*
      *  center_map
      *
      *  This function will center the map, showing all markers attached to this map
      *
      *  @type	function
      *  @date	8/11/2013
      *  @since	4.3.0
      *
      *  @param	map (Google Map object)
      *  @return	n/a
      */

      function center_map( map ) {

        // vars
        var bounds = new google.maps.LatLngBounds();

        // loop through all markers and create bounds
        $.each( map.markers, function( i, marker ){

          var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() );

          bounds.extend( latlng );

        });

        // only 1 marker?
        if( map.markers.length == 1 )
        {
          // set center of map
            map.setCenter( bounds.getCenter() );
            map.setZoom( 16 );
        }
        else
        {
          // fit to bounds
          map.fitBounds( bounds );
        }

      }

      /*
      *  document ready
      *
      *  This function will render each map when the document is ready (page has loaded)
      *
      *  @type	function
      *  @date	8/11/2013
      *  @since	5.0.0
      *
      *  @param	n/a
      *  @return	n/a
      */
      // global var
      var map = null;

      $(document).ready(function(){

        $('.gmap').each(function(){

          // create map
          map = new_map( $(this) );

        });

      });

      })(jQuery);
  },
};

I don’t understand why you are getting eslint error map is assigned a value but never used after disable no-unused-vars. It means that it is not disabled.

In other hand, I have exactly the same code with no errors:

https://bitbucket.org/aitormendez/superbiajuridico/src/master/web/app/themes/sj/resources/assets/scripts/routes/contact.js

have you tried yarn build && yarn start?

Thanks. I didn’t have the eslint error anymore, but it’s still not working properly. The map doesn’t appear in the template but I don’t know why. There are no errors in the js console and the code below properly retrieve the lat & lng data:

<div class="gmap">
  <div class="marker" data-lat="<?php echo $location['lat']; ?>" data-lng="<?php echo $location['lng']; ?>"></div>
</div>

FWIW, this can be used for elegantly setting the Google API key:

<?php
// Authorize API for project:
// https://console.developers.google.com/apis/api/places_backend?project=_

// Uses environment variable (WordPress Bedrock dotenv)

$google_api_key = getenv('GOOGLE_API_KEY');

if($google_api_key !== false and !empty($google_api_key)) {

  // ACF
  add_filter('acf/fields/google_map/api', function($value) {
	global $google_api_key;

    return array(
      'libraries' => 'places',
      'key'	      => $google_api_key
	);
  });

  // ACF PRO
  add_action('acf/init', function() {
	global $google_api_key;

    acf_update_setting('google_api_key', $google_api_key);
  });

}
2 Likes

This didn’t seem to be working for me. $google_api_key wasn’t getting to ACF option (though was there in settings.php). Not sure that there’s any harm in hardcoding it since it’s public in the request anyway, and should be API protected by caller.

Here’s some code for calling it with the latest Google Maps recommended class, and without jQuery:

(I have it in app.js.)

import {Loader} from '@googlemaps/js-api-loader';
// src: https://weichie.com/blog/acf-google-map-integration-using-vanilla-javascript/
class Map {
  constructor() {
    this.$el = document.querySelectorAll('.acf-map');

    this.map = null;

    this.loader = new Loader({
      apiKey: 'AIzaSyB-o-blablabla-2bA',
      version: 'weekly',
    });

    this.$el.forEach($el => {
      this.initMap($el);
    })
  }

  async initMap($el) {
    const $markers = $el.querySelectorAll('.marker');

    const mapOptions = {
      zoom: parseInt($el.dataset.zoom) || 16,
      mapTypeId: 'roadmap',
      mapId: 'JAGLETS_MAP_ID',
    };

    await this.loader.load();

    this.map = new google.maps.Map($el, mapOptions);
    this.map.markers = [];

    const markerPromises = [];

    $markers.forEach($marker => {
      markerPromises.push(async () => this.initMarker($marker, this.map));
    });

    const results = await Promise.allSettled(markerPromises);
    for (const result of results) {
      let marker = await result.value();
      this.map.markers.push(marker);
    }

    this.centerMap(this.map);
  }

  async initMarker($marker, map) {

    const lat = parseFloat($marker.dataset.lat);
    const lng = parseFloat($marker.dataset.lng);
    const latLng = {lat, lng};

    const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");

    const marker = new AdvancedMarkerElement({
      position: latLng,
      map: map,
    });

    if ($marker.innerHTML) {
      const infowindow = new google.maps.InfoWindow({
        content: $marker.innerHTML,
      });

      google.maps.event.addListener(marker, 'click', function () {
        infowindow.open(map, marker);
      });
    }

    return marker;
  }

  async centerMap(map) {
    const bounds = new google.maps.LatLngBounds();

    map.markers.forEach(marker => {
      bounds.extend({
        lat: marker.position.lat,
        lng: marker.position.lng,
      });
    });

    if (map.markers.length === 1) {
      map.setCenter(bounds.getCenter());
    } else {
      map.fitBounds(bounds);
    }
  }
};

domReady(async () => {
  //const flkty = new Flickity();
  const map = new Map();
  //. ...
}
1 Like

In the theme I use wp_localize_script to make the Google API key available on the frontend. This should also work in a plugin. IMHO this is the best approach for passing the API key from backend to frontend (and JavaScript running there).

1 Like