Skip to main content
Category:

Blocks, are pieces of content that can be placed anywhere on your Drupal site. in this tuto, I'll show you how to Create block Google Map in Drupal 8.

read this tuto to learn how to create custom block in drupal 8 https://codimth.com/blog/how-create-custom-block-drupal-8-programmatically.

create google_map.info.yml file:

name: Google Map Module
description: Module to Create a block showing Google Map.
package: Custom
type: module
core: 8.x

configure: google_map.settings

create config/install/google_map.settings.yml file:

here we add our default values.

width: 100%
height: 500px
zoom_level: 5
center_position: 1.154921,-21.224219
markers: 1.154921,-21.224219

create google_map.libraries.yml file:

add custom.js file to write our custom js code.

google-map-js:
  version: 1.x
  js:
    js/custom.js: {}
  dependencies:
    - core/jquery
    - core/drupal
    - core/drupalSettings

create google_map.links.menu.yml file:

add menu link to congfiguration form.

google_map.settings:
  title: 'Google Map'
  parent: system.admin_config_ui
  description: ''
  route_name: google_map.settings

create google_map.routing.yml file:

add custom route to configuration form.

google_map.settings:
  path: '/admin/config/user-interface/google_map'
  defaults:
    _form: '\Drupal\google_map\Form\GoogleMapForm'
    _title: 'Settings Form'
  requirements:
    _permission: 'access content'

create src/Form/GoogleMapForm.php file:

<?php

namespace Drupal\google_map\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;

class GoogleMapForm extends ConfigFormBase
{

    /**
     * {@inheritdoc}
     */
    public function getFormId()
    {
        return 'google_map_form';
    }

    /**
     * Gets the configuration names that will be editable.
     *
     * @return array
     *   An array of configuration object names that are editable if called in
     *   conjunction with the trait's config() method.
     */
    protected function getEditableConfigNames()
    {
        return [
            'google_map.settings',
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(array $form, FormStateInterface $form_state)
    {
        $form = parent::buildForm($form, $form_state);
        $config = $this->config('google_map.settings');

        $form['api_key'] = array(
            '#type' => 'textfield',
            '#title' => $this->t('api key for google map'),
            '#required' => TRUE,
            '#default_value' => $config->get('api_key'),
            '#description' => $this->t('Go to <a target="_blank" href="https://console.developers.google.com">https://console.developers.google.com</a> to get a free API key'),
        );

        return $form;
    }

    /**
     * {@inheritdoc}
     */
    public function validateForm(array &$form, FormStateInterface $form_state)
    {
        $api_key = $form_state->getValue('api_key');

        if (empty($api_key)) {
            $form_state->setErrorByName('api_key', $this->t('this field is required '));
        }
    }

    /**
     * {@inheritdoc}
     */
    public function submitForm(array &$form, FormStateInterface $form_state)
    {
        $config = $this->config('google_map.settings');
        $config->set('api_key', $form_state->getValue('api_key'));
        $config->save();
        parent::submitForm($form, $form_state);
    }


}

this class contains: 

getFormId(): This needs to return a string that is the unique ID of your form. Namespace the form ID based on your module's name.

buildForm(): This returns a Form API array that defines each of the elements of your form.

submitForm(): collect data and do things, like save the data to the database, send an email, or any number of other operations.

validateForm(): used to validate the data that's being collected.

this class return interface like this:

config form

create src/Plugin/Block/GoogleMapBlock.php file:

<?php

namespace Drupal\google_map\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a 'Google Map' Block.
 *
 * @Block(
 *   id = "google_map_block",
 *   admin_label = @Translation("Google Map block"),
 *   category = @Translation("Google Map block"),
 * )
 */
class GoogleMapBlock extends BlockBase implements BlockPluginInterface
{
    /**
     * {@inheritdoc}
     */
    public function defaultConfiguration()
    {
        $default_config = \Drupal::config('google_map.settings');
        return [
            'width' => $default_config->get('width'),
            'height' => $default_config->get('height'),
            'zoom_level' => $default_config->get('zoom_level'),
            'center_position' => $default_config->get('center_position'),
            'markers' => $default_config->get('markers'),
            'api_key' => $default_config->get('api_key'),
        ];
    }


    /**
     * {@inheritdoc}
     */
    public function build()
    {

        $config = $this->getConfiguration();

        return array(
            '#theme' => 'google_map',
            '#width' => $config['width'],
            '#height' => $config['height'],
            '#attached' => array(
                'library' => array(
                    'google_map/google-map-js',
                ),
                'drupalSettings' => [
                    'zoom' => $config['zoom_level'],
                    'center' => $config['center_position'],
                    'markers' => $config['markers'],
                    'api_key' => $config['api_key'],
                ]
            ),
        );
    }


    /**
     * {@inheritdoc}
     */
    public function blockForm($form, FormStateInterface $form_state)
    {
        $form = parent::blockForm($form, $form_state);
        $config = $this->getConfiguration();
        $form['width'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Width'),
            '#description' => $this->t('Width of your map '),
            '#default_value' => isset($config['width']) ? $config['width'] : '',
        ];
        $form['height'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Height'),
            '#description' => $this->t('Height of google your map '),
            '#default_value' => isset($config['height']) ? $config['height'] : '',
        ];
        $form['zoom_level'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Map Zoom Level'),
            '#default_value' => isset($config['zoom_level']) ? $config['zoom_level'] : '',
        ];

        $form['center_position'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Center Position'),
            '#placeholder' => "latitude,longitude",
            '#description' => $this->t('Use this link to get latitude and longitude <a target="_blank" href="https://www.latlong.net/">https://www.latlong.net/</a>'),
            '#default_value' => isset($config['center_position']) ? $config['center_position'] : '',
        ];


        $form['markers'] = [
            '#type' => 'textarea',
            '#title' => $this->t('Markers'),
            '#placeholder' => "latitude,longitude|latitude,longitude",
            '#description' => $this->t('Use | to separate markers. <br> Use this link to get latitude and longitude <a target="_blank" href="https://www.latlong.net/">https://www.latlong.net/</a>'),
            '#default_value' => isset($config['markers']) ? $config['markers'] : '',
        ];


        return $form;
    }


    /**
     * {@inheritdoc}
     */
    public function blockSubmit($form, FormStateInterface $form_state)
    {
        parent::blockSubmit($form, $form_state);
        $values = $form_state->getValues();
        $this->configuration['width'] = $values['width'];
        $this->configuration['height'] = $values['height'];
        $this->configuration['zoom_level'] = $values['zoom_level'];
        $this->configuration['center_position'] = $values['center_position'];
        $this->configuration['markers'] = $values['markers'];

    }

}

The class file should contain annotation as well. The annotation allows us to identify the bloc, also this class will contain 6 methods:

build(): required method which is expected to return a render array defining the content you want your block to display.

blockForm(): This method allows you to define a block configuration form using the Form API.

blockSubmit(): This method used to save a configuration, defined on the blockForm() method.

this class return interface like this:

Block Google Map

create js/custom.js file:

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

            var google_api_key = settings.api_key;
            var zoom = settings.zoom;
            var center_position = settings.center.split(",");
            var center_lat = center_position[0] ;
            var center_long = center_position[1];
            var markers = settings.markers.split("|");

            $.getScript('https://maps.googleapis.com/maps/api/js?key='+google_api_key,function () {

                var myCenter = new google.maps.LatLng(center_lat,center_long);
                var mapCanvas = document.getElementById("googleMap");
                var mapOptions = {
                    center: myCenter,
                    zoom: parseInt(zoom)
                };

                var map = new google.maps.Map(mapCanvas, mapOptions);

                var arrayLength = markers.length;
                for (var i = 0; i < arrayLength; i++) {
                    var mar = markers[i].split(",");
                    var marker = new google.maps.Marker({
                        position: new google.maps.LatLng(mar[0],mar[1])
                    });
                    marker.setMap(map);
                }



            });



        }
    };
})(jQuery, Drupal);


create google_map.module file:

<?php

/**
 * Implements hook_theme().
 */
function google_map_theme($existing, $type, $theme, $path) {
    return array(
        'google_map' => array(
            'variables' => array(
                'width' => NULL,
                'height' => NULL,
            )
        )
    );
}

create templates/google-map.html.twig file:

<div id="googleMap" style="width:{{ width }};height:{{ height }}">

</div>

Place the block to a region and it should become visible like this:

demo block google maps

Next steps

  • Clear your Drupal 8 caches. To do this I use this Drush command: drush cr if you don’t currently use Drush, I highly recommend using it, or the Drupal Console.
  • Now, go back to your site, and you should be able to see the block you have just created. Simply place the block to a region and it should become visible.
  • I hope you found this article useful. let me know if you have any questions and I’ll be happy to answer them.

 

Riadh Rahmi

Senior Web Developer PHP/Drupal & Laravel

I am a senior web developer, I have experience in planning and developing large scale dynamic web solutions especially in Drupal & Laravel.

Web Posts

Search

Page Facebook