Adding, removing and modifying map controls

Recall that almost anything you pass to the component is passed on as an option to the map. The options for controls are no exception. You can add or remove specific controls by setting the corresponding control variable to true or false. You can also pass in a g-map/hash to set further options. Learn more by following the guides at Controls Guide.

Let’s disable the default UI, make sure that we display the zoom control and move it to the top left.

<GMap
  @lat="51.507568"
  @lng="-0.127762"
  @zoom={{12}}
  @disableDefaultUI={{true}}
  @zoomControl={{true}}
  @zoomControlOptions={{g-map/hash
    position=this.google.maps.ControlPosition.LEFT_CENTER}} />

Tip Unfortunately, you have to reference the position using the constants defined under google.maps.ControlPosition. These actually map to integers that then define the position of the control. Now you wouldn’t normally have access to the google global in the template. A safe way of accessing it is via the googleMapsApi service. That way, when google is done initializing, the template will be updated with the position value.

import Controller from '@ember/controller';
import { inject as service } from '@ember/service';

export default class extends Controller {
  @service
  googleMapsApi;

  get google() {
    return this.googleMapsApi.google;
  }
}
Adding custom map controls

For more complex map UIs, you might want to add your own map controls to let the user initiate custom actions right from the map. Let’s try adding a button to the top center of the map that pans back to the center of London and sets the zoom level back to 12.

Test Try out the custom control to recenter the map.

The control component accepts a position attribute and a block template. The position is a string that specifies the placement of the control on the map. It should be one of the control position constants defined in ControlPosition. The component will map these to the correct google.maps.controlPosition behind the scenes. In our case, to place the control in the top center, we use TOP_CENTER. From there, we just bind an action to the button and pass the yielded map object.

<GMap
  @lat={{this.london.lat}}
  @lng={{this.london.lng}}
  @zoom={{12}}
  @disableDefaultUI={{true}}
  @mapTypeControl={{false}}
  @zoomControl={{true}}
  @zoomControlOptions={{g-map/hash
    position=this.google.maps.ControlPosition.TOP_LEFT}} as |map|>

  <map.marker @lat={{this.london.lat}} @lng={{this.london.lng}} />

  <map.control @position="TOP_CENTER">
    <div class="map-control">
      <button {{fn this.recenterMap map.map}} type="button" class="btn btn-light m-2">
        Recenter map
      </button>
    </div>
  </map.control>

</GMap>

In the controller (or component), we handle the action and recenter the map to wherever we want.

import Controller from '@ember/controller';
import { action } from '@ember/object';

export default class extends Controller {
  london = {
    lat: 51.507568,
    lng: -0.127762
  };

  @action
  recenterMap(map) {
    let { lat, lng } = this.london;
    map.setZoom(12);
    map.panTo({ lat, lng });
  }
}

Let’s look at how to query and display routing information.

Directions ›