diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..4fc0596e186490c44b86d42defcfa17931642318
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+  "globals": {
+    "L": true
+  }
+}
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..edece018b7d56c526d71bddb3e05c03572a90bed
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,31 @@
+################
+# GitLabCI template for Drupal projects.
+#
+# This template is designed to give any Contrib maintainer everything they need to test, without requiring modification.
+# It is also designed to keep up to date with Core Development automatically through the use of include files that can be centrally maintained.
+# As long as you include the project, ref and three files below, any future updates added by the Drupal Association will be used in your
+# pipelines automatically. However, you can modify this template if you have additional needs for your project.
+# The full documentation is on https://project.pages.drupalcode.org/gitlab_templates/
+################
+
+# For information on alternative values for 'ref' see https://project.pages.drupalcode.org/gitlab_templates/info/templates-version/
+# To test a Drupal 7 project, change the first include filename from .main.yml to .main-d7.yml
+include:
+  - project: $_GITLAB_TEMPLATES_REPO
+    ref: $_GITLAB_TEMPLATES_REF
+    file:
+      - '/includes/include.drupalci.main.yml'
+      - '/includes/include.drupalci.variables.yml'
+      - '/includes/include.drupalci.workflows.yml'
+#
+################
+# Pipeline configuration variables are defined with default values and descriptions in the file
+# https://git.drupalcode.org/project/gitlab_templates/-/blob/main/includes/include.drupalci.variables.yml
+# Uncomment the lines below if you want to override any of the variables. The following is just an example.
+################
+variables:
+  _CSPELL_WORDS:
+    value: 'bano, geolocate, latlon, zipcode'
+#   SKIP_ESLINT: '1'
+#   OPT_IN_TEST_NEXT_MAJOR: '1'
+#   _CURL_TEMPLATES_REF: 'main'
diff --git a/README.md b/README.md
index 02c1362a87abe275d8cad2fc403311d1498af2dd..bd73a612cc36e07241d6a3d00b4b88b84c238fb9 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
 # Geomap Field
 
-Provide a new field type to store address (using geolocation and map visualisation). Also provide a field formatter to display the field as a map.
\ No newline at end of file
+Provide a new field type to store address (using geolocation and map visualization). Also provide a field formatter to display the field as a map.
\ No newline at end of file
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..7013482f5b5ffa7ee4382acf1f82c92640693029
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,17 @@
+{
+  "name": "ecedi/geomap_field",
+  "description": "Provides geomap fields",
+  "type": "drupal-module",
+  "homepage": "https://www.drupal.org/project/geomap_field",
+  "authors": [
+    {
+      "name": "Marc-Antoine Marty (martygraphie)",
+      "role": "Maintainer"
+    }
+  ],
+  "license": "GPL-2.0-or-later",
+  "require": {
+    "drupal/geolocation_provider": "^1",
+    "drupal/map_provider" : "^1"
+  }
+}
\ No newline at end of file
diff --git a/css/geomap_default_widget.css b/css/geomap_default_widget.css
index 290d26a5c23e8eeba9e267137a215f20c03ff1e1..a73847793d2dccbaf4b87d70165a3db3e89496f8 100644
--- a/css/geomap_default_widget.css
+++ b/css/geomap_default_widget.css
@@ -20,17 +20,17 @@
 }
 
 .geomap-widget-map {
-  height: 100%;
   width: 100%;
+  height: 100%;
 }
 
 .geolocation-suggestions-list {
-  margin: 0;
-  padding: 0;
   position: absolute;
-  left: 11px;
-  bottom: 11px;
   z-index: 1000;
+  bottom: 11px;
+  left: 11px;
+  margin: 0;
+  padding: 0;
 }
 
 .geolocation-suggestions-list-item {
@@ -38,17 +38,17 @@
 }
 
 .geolocation-suggestions-list-item button {
+  display: flex;
+  align-items: center;
   padding: 8px 16px;
+  border: none;
   background-color: #fff;
   box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
-  border: none;
-  display: flex;
-  align-items: center;
 }
 
-.geolocation-suggestions-list-item button:after {
-  content: url(../images/baseline-reply-24px.svg);
+.geolocation-suggestions-list-item button::after {
   padding-left: 8px;
+  content: url(../images/baseline-reply-24px.svg);
 }
 
 .geolocation-suggestions-list-item button:hover {
@@ -56,16 +56,16 @@
 }
 
 .geomap-loader {
+  position: absolute;
+  z-index: 1000;
+  top: 16px;
+  right: 16px;
   width: 42px;
   height: 42px;
+  animation: geomap-loader-spin 1s linear infinite;
   border: 8px solid transparent;
   border-top: 8px solid #1f86c7;
   border-radius: 50%;
-  animation: geomap-loader-spin 1s linear infinite;
-  position: absolute;
-  z-index: 1000;
-  top: 16px;
-  right: 16px;
 }
 
 .geomap-loader[aria-hidden="true"] {
diff --git a/geomap_field.info.yml b/geomap_field.info.yml
index ddafbcac0a2a1fedfee69ab28d4082cd2f71eac6..0b5358a5e5f16116b3b6898ff7307c95e3b94823 100644
--- a/geomap_field.info.yml
+++ b/geomap_field.info.yml
@@ -1,6 +1,6 @@
 name: 'Geomap Field'
 type: module
-description: 'Provide a new field type to store address (using geolocation and map visualisation). Also provide a field formatter to display the field as a map.'
+description: 'Provide a new field type to store address (using geolocation and map visualization). Also provide a field formatter to display the field as a map.'
 core_version_requirement: ^8 || ^9 || ^10 || ^11
 package: 'Field types'
 dependencies:
diff --git a/geomap_field.services.yml b/geomap_field.services.yml
new file mode 100644
index 0000000000000000000000000000000000000000..faeeefecfda47521e255749997bc4004eec63dfc
--- /dev/null
+++ b/geomap_field.services.yml
@@ -0,0 +1,8 @@
+services:
+  plugin.manager.map_provider:
+    class: 'Drupal\map_provider\Plugin\MapProviderManager'
+    arguments: []
+
+  plugin.manager.geolocation_provider_plugin:
+    class: 'Drupal\geolocation_provider\Plugin\GeolocationProviderPluginManager'
+    arguments: ['@container.namespaces', '@cache.default', '@module_handler']
diff --git a/js/geomap-default-formatter.js b/js/geomap-default-formatter.js
index 4ba19a1cb6fb6060e5b687dc980cc5d7c6ebe669..876a7663a9b75fe4b786d7c93784f1f259f350da 100644
--- a/js/geomap-default-formatter.js
+++ b/js/geomap-default-formatter.js
@@ -3,25 +3,22 @@
  * Geomap default widget custom behavior
  */
 
-
 (function ($, Drupal) {
-
-    Drupal.behaviors.geomapDefaultFormatter = {
-
-        attach: function (context) {
-            $(once('geomapDefaultFormatter', '.geomap-formatter-map', context))
-                .on('map:afterInit', function (event, map) {
-                    var mapSettings = $(event.target).data('map');
-                    if (mapSettings.center) {
-                        var marker = new L.marker([
-                            mapSettings.center[0],
-                            mapSettings.center[1]
-                        ], {draggable: 'false'});
-                        map.addLayer(marker);
-                    }
-                }.bind(this));
-        }
-
-    };
-
+  Drupal.behaviors.geomapDefaultFormatter = {
+    attach(context) {
+      $(once('geomapDefaultFormatter', '.geomap-formatter-map', context)).on(
+        'map:afterInit',
+        function (event, map) {
+          const mapSettings = $(event.target).data('map');
+          if (mapSettings.center) {
+            const marker = new L.marker(
+              [mapSettings.center[0], mapSettings.center[1]],
+              { draggable: 'false' },
+            );
+            map.addLayer(marker);
+          }
+        },
+      );
+    },
+  };
 })(jQuery, Drupal);
diff --git a/js/geomap-default-widget.js b/js/geomap-default-widget.js
index e0f48a46294cddbbf84ecaa96b1beae0b8e4d225..806543f590f9836db4d1980309b62a791120a265 100644
--- a/js/geomap-default-widget.js
+++ b/js/geomap-default-widget.js
@@ -3,77 +3,95 @@
  * Geomap default widget custom behavior
  */
 
-
 (function ($, Drupal) {
-
   Drupal.behaviors.geomapDefaultWidget = {
+    attach(context) {
+      $(once('geomapDefaultWidget', '.geomap-widget-map', context)).on(
+        'map:afterInit',
+        function (event, map) {
+          const $map = $(event.target);
+          const geolocationPlugin = $map.data('geolocation-plugin');
+          const reverseUrl = `/geolocation_provider/reverse/${geolocationPlugin}`;
+          const geolocationUrl = `/geolocation_provider/geolocation/${geolocationPlugin}`;
+          const $widget = $map.parents('.geomap-widget-wrapper');
+          const $latlon = $widget.find('.latlon-wrapper');
+          const $latField = $latlon.find('.geomap-field-lat');
+          const $lonField = $latlon.find('.geomap-field-lon');
 
-    attach: function (context) {
-      $(once('geomapDefaultWidget','.geomap-widget-map', context))
-          .on('map:afterInit', function (event, map) {
-            var $map = $(event.target);
-            var geolocationPlugin = $map.data('geolocation-plugin');
-            var reverseUrl = '/geolocation_provider/reverse/' + geolocationPlugin;
-            var geolocationUrl = '/geolocation_provider/geolocation/' + geolocationPlugin;
-            var $widget = $map.parents('.geomap-widget-wrapper');
-            var $latlon = $widget.find('.latlon-wrapper');
-            var $latField = $latlon.find('.geomap-field-lat');
-            var $lonField = $latlon.find('.geomap-field-lon');
-
-            var marker = new L.marker([
-              $latField.val() || 51.505,
-              $lonField.val() || -0.09
-            ], {draggable: 'true'});
-            marker.on('dragend', function (event) {
-              var position = marker.getLatLng();
-              $latField.val(position.lat);
-              $lonField.val(position.lng);
+          const marker = new L.marker(
+            [$latField[0].value || 51.505, $lonField[0].value || -0.09],
+            { draggable: 'true' },
+          );
+          marker.on(
+            'dragend',
+            function (event) {
+              const position = marker.getLatLng();
+              $latField[0].value = position.lat;
+              $lonField[0].value = position.lng;
               this.updateLoader($widget, true);
-              $.get(reverseUrl + '/' + position.lat + '/' + position.lng, function (data) {
-                this.updateSuggestions($widget, data);
-                this.updateLoader($widget, false);
-                if (data.features && data.features.length > 0) {
-                  this.updateFeatureInput($widget, data.features[0]);
-                }
-              }.bind(this));
-            }.bind(this));
-            map.addLayer(marker);
-            $widget.marker = marker;
+              $.get(
+                `${reverseUrl}/${position.lat}/${position.lng}`,
+                function (data) {
+                  this.updateSuggestions($widget, data);
+                  this.updateLoader($widget, false);
+                  if (data.features && data.features.length > 0) {
+                    this.updateFeatureInput($widget, data.features[0]);
+                  }
+                }.bind(this),
+              );
+            }.bind(this),
+          );
+          map.addLayer(marker);
+          $widget.marker = marker;
 
-            // Listen Lat/Lon fields changes.
-            $latlon.find('input').on('input', Drupal.debounce(function (event) {
-              this.updateMarker($widget, map);
-            }.bind(this), 200));
+          // Listen Lat/Lon fields changes.
+          $latlon.find('input').on(
+            'input',
+            Drupal.debounce(
+              function (event) {
+                this.updateMarker($widget, map);
+              }.bind(this),
+              200,
+            ),
+          );
 
-            // Geolocation behavior.
-            $widget.find('.geomap-geolocation-btn').on('click', function (event) {
-              var street = $widget.find('input[name$="][street]"]').val();
-              var zipcode = $widget.find('input[name$="][zipcode]"]').val();
-              var city = $widget.find('input[name$="][city]"]').val();
-              var country = $widget.find('input[name$="][country]"]').val();
-              var address = street + ', ' + zipcode + ' ' + city + ', ' + country;
+          // Geolocation behavior.
+          $widget.find('.geomap-geolocation-btn').on(
+            'click',
+            function (event) {
+              const street = $widget.find('input[name$="][street]"]')[0].value;
+              const zipcode = $widget.find('input[name$="][zipcode]"]')[0]
+                .value;
+              const city = $widget.find('input[name$="][city]"]')[0].value;
+              const country = $widget.find('input[name$="][country]"]')[0]
+                .value;
+              const address = `${street}, ${zipcode} ${city}, ${country}`;
               this.updateLoader($widget, true);
-              $.get(geolocationUrl + '/' + address, function (data) {
-                this.updateLoader($widget, false);
-                if (data.features && data.features.length > 0) {
-                  var feature = data.features[0];
-                  $latField.val(feature.geometry.coordinates[1]);
-                  $lonField.val(feature.geometry.coordinates[0]);
-                  this.updateMarker($widget, map);
-                  this.updateFeatureInput($widget, feature);
-                }
-              }.bind(this));
+              $.get(
+                `${geolocationUrl}/${address}`,
+                function (data) {
+                  this.updateLoader($widget, false);
+                  if (data.features && data.features.length > 0) {
+                    const feature = data.features[0];
+                    $latField[0].value = feature.geometry.coordinates[1];
+                    $lonField[0].value = feature.geometry.coordinates[0];
+                    this.updateMarker($widget, map);
+                    this.updateFeatureInput($widget, feature);
+                  }
+                }.bind(this),
+              );
               event.preventDefault();
-            }.bind(this));
-
-          }.bind(this));
+            }.bind(this),
+          );
+        }.bind(this),
+      );
     },
 
-    updateMarker: function ($widget, map) {
-      var lat = $widget.find('.geomap-field-lat').val();
-      var lon = $widget.find('.geomap-field-lon').val();
+    updateMarker($widget, map) {
+      const lat = $widget.find('.geomap-field-lat')[0].value;
+      const lon = $widget.find('.geomap-field-lon')[0].value;
       if (lat && lon) {
-        var latlon = new L.LatLng(lat, lon);
+        const latlon = new L.LatLng(lat, lon);
         if (latlon !== $widget.marker.getLatLng()) {
           $widget.marker.setLatLng(latlon);
           map.setView(latlon);
@@ -81,40 +99,47 @@
       }
     },
 
-    updateLoader: function ($widget, status) {
-      $widget.find('.geomap-loader').attr('aria-hidden', status ? 'false' : 'true');
+    updateLoader($widget, status) {
+      $widget
+        .find('.geomap-loader')
+        .attr('aria-hidden', status ? 'false' : 'true');
     },
 
-    updateSuggestions: function ($widget, featureCollection) {
-      var $list = $widget.find('.geolocation-suggestions-list');
+    updateSuggestions($widget, featureCollection) {
+      const $list = $widget.find('.geolocation-suggestions-list');
       $list.empty();
-      var features = featureCollection.features || [];
-      features.forEach(function (feature) {
-        var $item = $('<li>', {'class': 'geolocation-suggestions-list-item'});
-        var $btn = $('<button>');
-        $btn.data('feature', feature);
-        $btn.on('click', this.onSuggestionClick.bind(this));
-        $btn.text(feature.properties.label)
-        $list.append($item.append($btn));
-      }.bind(this));
+      const features = featureCollection.features || [];
+      features.forEach(
+        function (feature) {
+          const $item = $('<li>', {
+            class: 'geolocation-suggestions-list-item',
+          });
+          const $btn = $('<button>');
+          $btn.data('feature', feature);
+          $btn.on('click', this.onSuggestionClick.bind(this));
+          $btn.get(0).textContent = feature.properties.label;
+          $list.append($item.append($btn));
+        }.bind(this),
+      );
     },
 
-    onSuggestionClick: function (event) {
-      var $suggestion = $(event.target);
-      var feature = $suggestion.data('feature');
+    onSuggestionClick(event) {
+      const $suggestion = $(event.target);
+      const feature = $suggestion.data('feature');
       // Update address input fields.
-      var $widget = $suggestion.parents('.geomap-widget-wrapper');
-      $widget.find('input[name$="][street]"]').val(feature.properties.name);
-      $widget.find('input[name$="][zipcode]"]').val(feature.properties.postcode);
-      $widget.find('input[name$="][city]"]').val(feature.properties.city);
+      const $widget = $suggestion.parents('.geomap-widget-wrapper');
+      $widget.find('input[name$="][street]"]')[0].value =
+        feature.properties.name;
+      $widget.find('input[name$="][zipcode]"]')[0].value =
+        feature.properties.postcode;
+      $widget.find('input[name$="][city]"]')[0].value = feature.properties.city;
       this.updateFeatureInput($widget, feature);
       event.preventDefault();
     },
 
-    updateFeatureInput: function ($widget, feature) {
-      $widget.find('input[name$="][feature]"]').val(JSON.stringify(feature));
-    }
-
+    updateFeatureInput($widget, feature) {
+      $widget.find('input[name$="][feature]"]')[0].value =
+        JSON.stringify(feature);
+    },
   };
-
 })(jQuery, Drupal);
diff --git a/src/Plugin/Field/FieldFormatter/GeomapDefault.php b/src/Plugin/Field/FieldFormatter/GeomapDefault.php
index e367038ccd960168f3a189d2452df4250914acdf..d0f20d0095dbfe03b5c7dae8090db7743d8904b4 100644
--- a/src/Plugin/Field/FieldFormatter/GeomapDefault.php
+++ b/src/Plugin/Field/FieldFormatter/GeomapDefault.php
@@ -2,9 +2,12 @@
 
 namespace Drupal\geomap_field\Plugin\Field\FieldFormatter;
 
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FormatterBase;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\map_provider\Plugin\MapProviderManager;
 
 /**
  * Plugin implementation of the 'geomap_default' formatter.
@@ -19,6 +22,36 @@ use Drupal\Core\Form\FormStateInterface;
  */
 class GeomapDefault extends FormatterBase {
 
+  /**
+   * Map manager service.
+   *
+   * @var \Drupal\map_provider\Plugin\MapProviderManager
+   */
+  protected MapProviderManager $mapManager;
+
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, MapProviderManager $mapManager) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
+    $this->mapManager = $mapManager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+
+    $mapManager = $container->get('plugin.manager.map_provider');
+    return new static(
+      $plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['label'],
+      $configuration['view_mode'],
+      $configuration['third_party_settings'],
+      $mapManager
+    );
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -36,11 +69,8 @@ class GeomapDefault extends FormatterBase {
    */
   public function settingsForm(array $form, FormStateInterface $form_state) {
     $elements = [];
-
-    /** @var \Drupal\map_provider\Plugin\MapProviderManager $map_manager */
-    $map_manager = \Drupal::service('plugin.manager.map_provider');
     $map_options = [];
-    foreach ($map_manager->getDefinitions() as $id => $definition) {
+    foreach ($this->mapManager->getDefinitions() as $id => $definition) {
       $map_options[$id] = $definition['label'];
     }
     $elements['map_provider'] = [
@@ -71,10 +101,7 @@ class GeomapDefault extends FormatterBase {
    */
   public function settingsSummary() {
     $summary = [];
-
-    /** @var \Drupal\map_provider\Plugin\MapProviderManager $map_manager */
-    $map_manager = \Drupal::service('plugin.manager.map_provider');
-    $map_plugin_label = $map_manager->getDefinition($this->getSetting('map_provider'))['label'] ?? '';
+    $map_plugin_label = $this->mapManager->getDefinition($this->getSetting('map_provider'))['label'] ?? '';
     $summary[] = $this->t('Map provider: @provider', ['@provider' => $map_plugin_label]);
 
     $summary[] = $this->t('Map height: @height', ['@height' => $this->getSetting('height')]);
@@ -88,8 +115,6 @@ class GeomapDefault extends FormatterBase {
    */
   public function viewElements(FieldItemListInterface $items, $langcode) {
     $elements = [];
-    /** @var \Drupal\map_provider\Plugin\MapProviderManager $map_manager */
-    $map_manager = \Drupal::service('plugin.manager.map_provider');
 
     foreach ($items as $delta => $item) {
       /** @var \Drupal\map_provider\Plugin\MapProviderInterface $map_provider */
@@ -97,7 +122,7 @@ class GeomapDefault extends FormatterBase {
       if (empty($plugin)) {
         $plugin = 'yaml_map_provider:osm';
       }
-      $map_provider = $map_manager->createInstance($plugin);
+      $map_provider = $this->mapManager->createInstance($plugin);
       $elements[$delta] = [
         '#type' => 'map',
         '#tile_url' => $map_provider->getUrl(),
diff --git a/src/Plugin/Field/FieldType/GeomapItem.php b/src/Plugin/Field/FieldType/GeomapItem.php
index 38fb21125639aee6cf411a637ee412eb8a64c921..485def330ce6c060a7c55e3b49d6db7e0060a38b 100644
--- a/src/Plugin/Field/FieldType/GeomapItem.php
+++ b/src/Plugin/Field/FieldType/GeomapItem.php
@@ -26,9 +26,9 @@ class GeomapItem extends FieldItemBase {
    */
   public static function defaultStorageSettings() {
     $default = [
-      //      'max_length' => 255,
-      //      'is_ascii' => FALSE,
-      //      'case_sensitive' => FALSE,
+      // 'max_length' => 255,
+      // 'is_ascii' => FALSE,
+      // 'case_sensitive' => FALSE,
     ];
     return $default + parent::defaultStorageSettings();
   }
diff --git a/src/Plugin/Field/FieldWidget/GeomapDefault.php b/src/Plugin/Field/FieldWidget/GeomapDefault.php
index 80867adb144ba3449b665b1758e0ccbb1e6854f2..9067cb4e4f888bd6657e8074336ae32df11f96e9 100644
--- a/src/Plugin/Field/FieldWidget/GeomapDefault.php
+++ b/src/Plugin/Field/FieldWidget/GeomapDefault.php
@@ -2,9 +2,13 @@
 
 namespace Drupal\geomap_field\Plugin\Field\FieldWidget;
 
+use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\WidgetBase;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\geolocation_provider\Plugin\GeolocationProviderPluginManager;
+use Drupal\map_provider\Plugin\MapProviderManager;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Plugin implementation of the 'geomap_default' widget.
@@ -19,6 +23,43 @@ use Drupal\Core\Form\FormStateInterface;
  */
 class GeomapDefault extends WidgetBase {
 
+  /**
+   * GeolocationProvider service.
+   *
+   * @var \Drupal\geolocation_provider\Plugin\GeolocationProviderPluginManager
+   */
+  protected GeolocationProviderPluginManager $geolocationManager;
+
+  /**
+   * Map manager service.
+   *
+   * @var \Drupal\map_provider\Plugin\MapProviderManager
+   */
+  protected MapProviderManager $mapManager;
+
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, GeolocationProviderPluginManager $geolocationManager, MapProviderManager $mapManager) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
+    $this->geolocationManager = $geolocationManager;
+    $this->mapManager = $mapManager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    $geolocationManager = $container->get('plugin.manager.geolocation_provider_plugin');
+    $mapManager = $container->get('plugin.manager.map_provider');
+    return new static(
+      $plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['third_party_settings'],
+      $geolocationManager,
+      $mapManager
+    );
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -35,11 +76,8 @@ class GeomapDefault extends WidgetBase {
    */
   public function settingsForm(array $form, FormStateInterface $form_state) {
     $elements = [];
-
-    /** @var \Drupal\geolocation_provider\Plugin\GeolocationProviderPluginManager $geolocation_manager */
-    $geolocation_manager = \Drupal::service('plugin.manager.geolocation_provider_plugin');
     $geo_options = [];
-    foreach ($geolocation_manager->getDefinitions() as $id => $definition) {
+    foreach ($this->geolocationManager->getDefinitions() as $id => $definition) {
       $geo_options[$id] = $definition['label'];
     }
     $elements['geolocation_provider'] = [
@@ -48,11 +86,8 @@ class GeomapDefault extends WidgetBase {
       '#options' => $geo_options,
       '#default_value' => $this->settings['geolocation_provider'],
     ];
-
-    /** @var \Drupal\map_provider\Plugin\MapProviderManager $map_manager */
-    $map_manager = \Drupal::service('plugin.manager.map_provider');
     $map_options = [];
-    foreach ($map_manager->getDefinitions() as $id => $definition) {
+    foreach ($this->mapManager->getDefinitions() as $id => $definition) {
       $map_options[$id] = $definition['label'];
     }
     $elements['map_provider'] = [
@@ -70,15 +105,9 @@ class GeomapDefault extends WidgetBase {
    */
   public function settingsSummary() {
     $summary = [];
-
-    /** @var \Drupal\geolocation_provider\Plugin\GeolocationProviderPluginManager $geolocation_manager */
-    $geolocation_manager = \Drupal::service('plugin.manager.geolocation_provider_plugin');
-    $geolocation_plugin_label = $geolocation_manager->getDefinition($this->getSetting('geolocation_provider'))['label'] ?? '';
+    $geolocation_plugin_label = $this->geolocationManager->getDefinition($this->getSetting('geolocation_provider'))['label'] ?? '';
     $summary[] = t('Geolocation provider: @provider', ['@provider' => $geolocation_plugin_label]);
-
-    /** @var \Drupal\map_provider\Plugin\MapProviderManager $map_manager */
-    $map_manager = \Drupal::service('plugin.manager.map_provider');
-    $map_plugin_label = $map_manager->getDefinition($this->getSetting('map_provider'))['label'] ?? '';
+    $map_plugin_label = $this->mapManager->getDefinition($this->getSetting('map_provider'))['label'] ?? '';
     $summary[] = t('Map provider: @provider', ['@provider' => $map_plugin_label]);
 
     return $summary;
@@ -90,10 +119,8 @@ class GeomapDefault extends WidgetBase {
   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
     /** @var \Drupal\geomap_field\Plugin\Field\FieldType\GeomapItem $item */
     $item = $items[$delta];
-    /** @var \Drupal\map_provider\Plugin\MapProviderManager $map_manager */
-    $map_manager = \Drupal::service('plugin.manager.map_provider');
     /** @var \Drupal\map_provider\Plugin\MapProviderInterface $map_provider */
-    $map_provider = $map_manager->createInstance($this->getSetting('map_provider'));
+    $map_provider = $this->mapManager->createInstance($this->getSetting('map_provider'));
     $geomap_form = [
       '#type' => 'details',
       '#open' => TRUE,